blob: 81e20aaf13ee2c064f3c809545bf893b2985d2bd [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;
Selim Cinekeaa29ca2015-11-23 13:51:13 -080028import android.view.NotificationHeaderView;
Dan Sandlera5e0f412014-01-23 15:11:54 -050029import android.view.View;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +020030import android.view.ViewStub;
Jorim Jaggife40f7d2014-04-28 15:20:04 +020031import android.view.accessibility.AccessibilityEvent;
Selim Cinekb5605e52015-02-20 18:21:41 +010032import android.view.animation.LinearInterpolator;
Selim Cinek98713a42015-09-21 15:47:20 +020033import android.widget.Chronometer;
Selim Cinekcab4a602014-09-03 14:47:57 +020034import android.widget.ImageView;
Selim Cinekeaa29ca2015-11-23 13:51:13 -080035import android.widget.RemoteViews;
Selim Cinekb5605e52015-02-20 18:21:41 +010036
Dan Sandlera5e0f412014-01-23 15:11:54 -050037import com.android.systemui.R;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -070038import com.android.systemui.classifier.FalsingManager;
Selim Cinekb5605e52015-02-20 18:21:41 +010039import com.android.systemui.statusbar.phone.NotificationGroupManager;
Selim Cinekb5605e52015-02-20 18:21:41 +010040import com.android.systemui.statusbar.stack.NotificationChildrenContainer;
41import com.android.systemui.statusbar.stack.StackScrollState;
42import com.android.systemui.statusbar.stack.StackStateAnimator;
43import com.android.systemui.statusbar.stack.StackViewState;
44
45import java.util.List;
Dan Sandlera5e0f412014-01-23 15:11:54 -050046
Jorim Jaggi4222d9a2014-04-23 16:13:15 +020047public class ExpandableNotificationRow extends ActivatableNotificationView {
Selim Cinekb5605e52015-02-20 18:21:41 +010048
49 private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
50 private static final int COLORED_DIVIDER_ALPHA = 0x7B;
51 private final LinearInterpolator mLinearInterpolator = new LinearInterpolator();
Selim Cinek1685e632014-04-08 02:27:49 +020052 private int mRowMinHeight;
Chris Wren51c75102013-07-16 20:49:17 -040053
Selim Cinek1685e632014-04-08 02:27:49 +020054 /** Does this row contain layouts that can adapt to row expansion */
Chris Wren51c75102013-07-16 20:49:17 -040055 private boolean mExpandable;
Selim Cinek1685e632014-04-08 02:27:49 +020056 /** Has the user actively changed the expansion state of this row */
57 private boolean mHasUserChangedExpansion;
58 /** If {@link #mHasUserChangedExpansion}, has the user expanded this row */
Chris Wren51c75102013-07-16 20:49:17 -040059 private boolean mUserExpanded;
Selim Cinek1685e632014-04-08 02:27:49 +020060 /** Is the user touching this row */
Chris Wren51c75102013-07-16 20:49:17 -040061 private boolean mUserLocked;
Selim Cinek1685e632014-04-08 02:27:49 +020062 /** Are we showing the "public" version */
Dan Sandlera5e0f412014-01-23 15:11:54 -050063 private boolean mShowingPublic;
Jorim Jaggiae441282014-08-01 02:45:18 +020064 private boolean mSensitive;
65 private boolean mShowingPublicInitialized;
Selim Cinek60122be2015-04-15 18:16:50 -070066 private boolean mHideSensitiveForIntrinsicHeight;
Chris Wren51c75102013-07-16 20:49:17 -040067
Selim Cinek1685e632014-04-08 02:27:49 +020068 /**
69 * Is this notification expanded by the system. The expansion state can be overridden by the
70 * user expansion.
71 */
72 private boolean mIsSystemExpanded;
Jorim Jaggidce3c4c2014-04-29 23:12:24 +020073
74 /**
Selim Cinek83bc7832015-10-22 13:26:54 -070075 * Whether the notification is on the keyguard and the expansion is disabled.
Jorim Jaggidce3c4c2014-04-29 23:12:24 +020076 */
Selim Cinek83bc7832015-10-22 13:26:54 -070077 private boolean mOnKeyguard;
Jorim Jaggidce3c4c2014-04-29 23:12:24 +020078
Jorim Jaggibe565df2014-04-28 17:51:23 +020079 private NotificationContentView mPublicLayout;
80 private NotificationContentView mPrivateLayout;
Selim Cinek1685e632014-04-08 02:27:49 +020081 private int mMaxExpandHeight;
Selim Cinek8d490d42015-04-10 00:05:50 -070082 private int mHeadsUpHeight;
Selim Cinek863834b2014-05-20 04:20:25 +020083 private View mVetoButton;
Dan Sandler0d3e62f2014-07-14 17:13:50 -040084 private boolean mClearable;
Chris Wren78403d72014-07-28 10:23:24 +010085 private ExpansionLogger mLogger;
86 private String mLoggingKey;
Selim Cineka5e211b2014-08-11 17:35:48 +020087 private boolean mWasReset;
Selim Cinek8d490d42015-04-10 00:05:50 -070088 private NotificationGuts mGuts;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +020089 private StatusBarNotification mStatusBarNotification;
Selim Cinek1a521f32014-11-03 17:39:29 +010090 private boolean mIsHeadsUp;
Selim Cinek98713a42015-09-21 15:47:20 +020091 private boolean mLastChronometerRunning = true;
Selim Cinekeef84282015-10-30 16:28:00 -070092 private NotificationHeaderView mNotificationHeader;
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 Cinekb5605e52015-02-20 18:21:41 +010099 private boolean mIsSystemChildExpanded;
Selim Cinek684a4422015-04-15 16:18:39 -0700100 private boolean mIsPinned;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700101 private FalsingManager mFalsingManager;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200102
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700103 private boolean mJustClicked;
Selim Cinek5a175d92015-11-23 18:01:33 -0800104 private boolean mIconAnimationRunning;
Selim Cinek34d93b02015-10-22 12:30:38 -0700105 private boolean mShowNoBackground;
Selim Cinek388df6d2015-10-22 13:25:11 -0700106 private ExpandableNotificationRow mNotificationParent;
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800107 private OnClickListener mExpandClickListener = new OnClickListener() {
108 @Override
109 public void onClick(View v) {
110 if (mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
111 mGroupManager.toggleGroupExpansion(mStatusBarNotification);
112 } else {
113 setUserExpanded(!isExpanded());
114 notifyHeightChanged(true);
115 }
116 }
117 };
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700118
Selim Cinek8d490d42015-04-10 00:05:50 -0700119 public NotificationContentView getPrivateLayout() {
120 return mPrivateLayout;
121 }
122
123 public NotificationContentView getPublicLayout() {
124 return mPublicLayout;
125 }
126
Selim Cinekcab4a602014-09-03 14:47:57 +0200127 public void setIconAnimationRunning(boolean running) {
128 setIconAnimationRunning(running, mPublicLayout);
129 setIconAnimationRunning(running, mPrivateLayout);
Selim Cinek5a175d92015-11-23 18:01:33 -0800130 setIconAnimationRunningForChild(running, mNotificationHeader);
131 if (mIsSummaryWithChildren) {
132 List<ExpandableNotificationRow> notificationChildren =
133 mChildrenContainer.getNotificationChildren();
134 for (int i = 0; i < notificationChildren.size(); i++) {
135 ExpandableNotificationRow child = notificationChildren.get(i);
136 child.setIconAnimationRunning(running);
137 }
138 }
139 mIconAnimationRunning = running;
Selim Cinekcab4a602014-09-03 14:47:57 +0200140 }
141
142 private void setIconAnimationRunning(boolean running, NotificationContentView layout) {
143 if (layout != null) {
144 View contractedChild = layout.getContractedChild();
145 View expandedChild = layout.getExpandedChild();
Selim Cinek8d490d42015-04-10 00:05:50 -0700146 View headsUpChild = layout.getHeadsUpChild();
Selim Cinekcab4a602014-09-03 14:47:57 +0200147 setIconAnimationRunningForChild(running, contractedChild);
148 setIconAnimationRunningForChild(running, expandedChild);
Selim Cinek8d490d42015-04-10 00:05:50 -0700149 setIconAnimationRunningForChild(running, headsUpChild);
Selim Cinekcab4a602014-09-03 14:47:57 +0200150 }
151 }
152
153 private void setIconAnimationRunningForChild(boolean running, View child) {
154 if (child != null) {
155 ImageView icon = (ImageView) child.findViewById(com.android.internal.R.id.icon);
156 setIconRunning(icon, running);
157 ImageView rightIcon = (ImageView) child.findViewById(
158 com.android.internal.R.id.right_icon);
159 setIconRunning(rightIcon, running);
160 }
161 }
162
163 private void setIconRunning(ImageView imageView, boolean running) {
164 if (imageView != null) {
165 Drawable drawable = imageView.getDrawable();
166 if (drawable instanceof AnimationDrawable) {
167 AnimationDrawable animationDrawable = (AnimationDrawable) drawable;
168 if (running) {
169 animationDrawable.start();
170 } else {
171 animationDrawable.stop();
172 }
173 } else if (drawable instanceof AnimatedVectorDrawable) {
174 AnimatedVectorDrawable animationDrawable = (AnimatedVectorDrawable) drawable;
175 if (running) {
176 animationDrawable.start();
177 } else {
178 animationDrawable.stop();
179 }
180 }
181 }
182 }
183
Selim Cinek8fc93c92015-11-23 17:48:07 -0800184 public void updateStatusBarNotification(StatusBarNotification statusBarNotification) {
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200185 mStatusBarNotification = statusBarNotification;
Selim Cinek8fc93c92015-11-23 17:48:07 -0800186 mPrivateLayout.onNotificationUpdated(statusBarNotification);
187 mPublicLayout.onNotificationUpdated(statusBarNotification);
Selim Cineka37774f2014-11-11 19:16:18 +0100188 updateVetoButton();
Selim Cinek8fc93c92015-11-23 17:48:07 -0800189 if (mIsSummaryWithChildren) {
190 recreateNotificationHeader();
191 }
Selim Cinek5a175d92015-11-23 18:01:33 -0800192 if (mIconAnimationRunning) {
193 setIconAnimationRunning(true);
194 }
Selim Cinek263398f2015-10-21 17:40:23 -0700195 onChildrenCountChanged();
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200196 }
197
198 public StatusBarNotification getStatusBarNotification() {
199 return mStatusBarNotification;
200 }
201
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700202 public boolean isHeadsUp() {
203 return mIsHeadsUp;
204 }
205
Selim Cinek1a521f32014-11-03 17:39:29 +0100206 public void setHeadsUp(boolean isHeadsUp) {
Selim Cinekc80fdb12015-04-13 15:09:08 -0700207 int intrinsicBefore = getIntrinsicHeight();
Selim Cinek1a521f32014-11-03 17:39:29 +0100208 mIsHeadsUp = isHeadsUp;
Selim Cinek8d490d42015-04-10 00:05:50 -0700209 mPrivateLayout.setHeadsUp(isHeadsUp);
Selim Cinekc80fdb12015-04-13 15:09:08 -0700210 if (intrinsicBefore != getIntrinsicHeight()) {
211 notifyHeightChanged(false /* needsAnimation */);
212 }
Selim Cinek1a521f32014-11-03 17:39:29 +0100213 }
214
Selim Cinekb5605e52015-02-20 18:21:41 +0100215 public void setGroupManager(NotificationGroupManager groupManager) {
216 mGroupManager = groupManager;
Selim Cinek83bc7832015-10-22 13:26:54 -0700217 mPrivateLayout.setGroupManager(groupManager);
Selim Cinekb5605e52015-02-20 18:21:41 +0100218 }
219
220 public void addChildNotification(ExpandableNotificationRow row) {
221 addChildNotification(row, -1);
222 }
223
224 /**
225 * Add a child notification to this view.
226 *
227 * @param row the row to add
228 * @param childIndex the index to add it at, if -1 it will be added at the end
229 */
230 public void addChildNotification(ExpandableNotificationRow row, int childIndex) {
231 if (mChildrenContainer == null) {
232 mChildrenContainerStub.inflate();
233 }
234 mChildrenContainer.addNotification(row, childIndex);
Selim Cinek263398f2015-10-21 17:40:23 -0700235 onChildrenCountChanged();
236 row.setIsChildInGroup(true, this);
Selim Cinekb5605e52015-02-20 18:21:41 +0100237 }
238
239 public void removeChildNotification(ExpandableNotificationRow row) {
240 if (mChildrenContainer != null) {
241 mChildrenContainer.removeNotification(row);
242 }
Selim Cinek263398f2015-10-21 17:40:23 -0700243 onChildrenCountChanged();
244 row.setIsChildInGroup(false, null);
245 }
246
247 public boolean isChildInGroup() {
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700248 return mNotificationParent != null;
Selim Cinek263398f2015-10-21 17:40:23 -0700249 }
250
Selim Cinek388df6d2015-10-22 13:25:11 -0700251 public ExpandableNotificationRow getNotificationParent() {
252 return mNotificationParent;
253 }
254
Selim Cinek263398f2015-10-21 17:40:23 -0700255 /**
256 * @param isChildInGroup Is this notification now in a group
257 * @param parent the new parent notification
258 */
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700259 public void setIsChildInGroup(boolean isChildInGroup, ExpandableNotificationRow parent) {;
260 boolean childInGroup = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup;
261 mNotificationParent = childInGroup ? parent : null;
262 mPrivateLayout.setIsChildInGroup(childInGroup);
263 updateNoBackgroundState();
Selim Cinek34d93b02015-10-22 12:30:38 -0700264 }
265
266 @Override
267 protected boolean shouldHideBackground() {
268 return super.shouldHideBackground() || mShowNoBackground;
Selim Cinek263398f2015-10-21 17:40:23 -0700269 }
270
271 @Override
272 public boolean isSummaryWithChildren() {
273 return mIsSummaryWithChildren;
Selim Cinekb5605e52015-02-20 18:21:41 +0100274 }
275
276 @Override
277 public boolean areChildrenExpanded() {
278 return mChildrenExpanded;
279 }
280
281 public List<ExpandableNotificationRow> getNotificationChildren() {
282 return mChildrenContainer == null ? null : mChildrenContainer.getNotificationChildren();
283 }
284
Selim Cinekeef84282015-10-30 16:28:00 -0700285 public int getNumberOfNotificationChildren() {
286 if (mChildrenContainer == null) {
287 return 0;
288 }
289 return mChildrenContainer.getNotificationChildren().size();
290 }
291
Selim Cinekb5605e52015-02-20 18:21:41 +0100292 /**
293 * Apply the order given in the list to the children.
294 *
295 * @param childOrder the new list order
296 * @return whether the list order has changed
297 */
298 public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder) {
299 return mChildrenContainer != null && mChildrenContainer.applyChildOrder(childOrder);
300 }
301
302 public void getChildrenStates(StackScrollState resultState) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700303 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100304 StackViewState parentState = resultState.getViewStateForView(this);
305 mChildrenContainer.getState(resultState, parentState);
306 }
307 }
308
309 public void applyChildrenState(StackScrollState state) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700310 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100311 mChildrenContainer.applyState(state);
312 }
313 }
314
315 public void prepareExpansionChanged(StackScrollState state) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700316 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100317 mChildrenContainer.prepareExpansionChanged(state);
318 }
319 }
320
321 public void startChildAnimation(StackScrollState finalState,
322 StackStateAnimator stateAnimator, boolean withDelays, long delay, long duration) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700323 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100324 mChildrenContainer.startAnimationToState(finalState, stateAnimator, withDelays, delay,
325 duration);
326 }
327 }
328
329 public ExpandableNotificationRow getViewAtPosition(float y) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700330 if (!mIsSummaryWithChildren || !mChildrenExpanded) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100331 return this;
332 } else {
333 ExpandableNotificationRow view = mChildrenContainer.getViewAtPosition(y);
334 return view == null ? this : view;
335 }
336 }
337
Selim Cinekab29aeb2015-02-20 18:18:32 +0100338 public NotificationGuts getGuts() {
339 return mGuts;
340 }
341
Selim Cinek684a4422015-04-15 16:18:39 -0700342 /**
343 * Set this notification to be pinned to the top if {@link #isHeadsUp()} is true. By doing this
344 * the notification will be rendered on top of the screen.
345 *
346 * @param pinned whether it is pinned
347 */
348 public void setPinned(boolean pinned) {
349 mIsPinned = pinned;
Selim Cinek98713a42015-09-21 15:47:20 +0200350 setChronometerRunning(mLastChronometerRunning);
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700351 }
352
Selim Cinek684a4422015-04-15 16:18:39 -0700353 public boolean isPinned() {
354 return mIsPinned;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700355 }
356
357 public int getHeadsUpHeight() {
Selim Cinek8d490d42015-04-10 00:05:50 -0700358 return mHeadsUpHeight;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700359 }
360
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700361 /**
362 * Mark whether this notification was just clicked, i.e. the user has just clicked this
363 * notification in this frame.
364 */
365 public void setJustClicked(boolean justClicked) {
366 mJustClicked = justClicked;
367 }
368
369 /**
370 * @return true if this notification has been clicked in this frame, false otherwise
371 */
372 public boolean wasJustClicked() {
373 return mJustClicked;
374 }
375
Selim Cinek98713a42015-09-21 15:47:20 +0200376 public void setChronometerRunning(boolean running) {
377 mLastChronometerRunning = running;
378 setChronometerRunning(running, mPrivateLayout);
379 setChronometerRunning(running, mPublicLayout);
380 if (mChildrenContainer != null) {
381 List<ExpandableNotificationRow> notificationChildren =
382 mChildrenContainer.getNotificationChildren();
383 for (int i = 0; i < notificationChildren.size(); i++) {
384 ExpandableNotificationRow child = notificationChildren.get(i);
385 child.setChronometerRunning(running);
386 }
387 }
388 }
389
390 private void setChronometerRunning(boolean running, NotificationContentView layout) {
391 if (layout != null) {
392 running = running || isPinned();
393 View contractedChild = layout.getContractedChild();
394 View expandedChild = layout.getExpandedChild();
395 View headsUpChild = layout.getHeadsUpChild();
396 setChronometerRunningForChild(running, contractedChild);
397 setChronometerRunningForChild(running, expandedChild);
398 setChronometerRunningForChild(running, headsUpChild);
399 }
400 }
401
402 private void setChronometerRunningForChild(boolean running, View child) {
403 if (child != null) {
404 View chronometer = child.findViewById(com.android.internal.R.id.chronometer);
405 if (chronometer instanceof Chronometer) {
406 ((Chronometer) chronometer).setStarted(running);
407 }
408 }
409 }
410
Selim Cinek8d6440d2015-10-22 13:00:05 -0700411 public CharSequence getSubText() {
412 Notification notification = mStatusBarNotification.getNotification();
413 CharSequence subText = notification.extras.getCharSequence(Notification.EXTRA_SUMMARY_TEXT);
414 if (subText == null) {
415 subText = notification.extras.getCharSequence(Notification.EXTRA_SUB_TEXT);
416 }
417 return subText;
418 }
419
420 public void setContentSubTextVisible(boolean visible) {
421 mPrivateLayout.setSubTextVisible(visible);
422 }
423
Chris Wren78403d72014-07-28 10:23:24 +0100424 public interface ExpansionLogger {
425 public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
426 }
Selim Cinek1685e632014-04-08 02:27:49 +0200427
Chris Wren51c75102013-07-16 20:49:17 -0400428 public ExpandableNotificationRow(Context context, AttributeSet attrs) {
429 super(context, attrs);
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700430 mFalsingManager = FalsingManager.getInstance(context);
Chris Wren51c75102013-07-16 20:49:17 -0400431 }
432
Christoph Studera7fe6312014-06-27 19:32:44 +0200433 /**
434 * Resets this view so it can be re-used for an updated notification.
435 */
Christoph Studer22f2ee52014-07-29 22:57:21 +0200436 @Override
Christoph Studera7fe6312014-06-27 19:32:44 +0200437 public void reset() {
Christoph Studer22f2ee52014-07-29 22:57:21 +0200438 super.reset();
Christoph Studera7fe6312014-06-27 19:32:44 +0200439 mRowMinHeight = 0;
Chris Wren78403d72014-07-28 10:23:24 +0100440 final boolean wasExpanded = isExpanded();
Selim Cinek379ff8f2015-02-20 17:03:16 +0100441 mMaxViewHeight = 0;
Christoph Studera7fe6312014-06-27 19:32:44 +0200442 mExpandable = false;
443 mHasUserChangedExpansion = false;
444 mUserLocked = false;
445 mShowingPublic = false;
Jorim Jaggiae441282014-08-01 02:45:18 +0200446 mSensitive = false;
447 mShowingPublicInitialized = false;
Christoph Studera7fe6312014-06-27 19:32:44 +0200448 mIsSystemExpanded = false;
Selim Cinek83bc7832015-10-22 13:26:54 -0700449 mOnKeyguard = false;
Selim Cinek1a521f32014-11-03 17:39:29 +0100450 mPublicLayout.reset(mIsHeadsUp);
451 mPrivateLayout.reset(mIsHeadsUp);
Selim Cinek31094df2014-08-14 19:28:15 +0200452 resetHeight();
453 logExpansionEvent(false, wasExpanded);
454 }
455
456 public void resetHeight() {
Selim Cinek1a521f32014-11-03 17:39:29 +0100457 if (mIsHeadsUp) {
458 resetActualHeight();
459 }
Christoph Studera7fe6312014-06-27 19:32:44 +0200460 mMaxExpandHeight = 0;
Selim Cinek8d490d42015-04-10 00:05:50 -0700461 mHeadsUpHeight = 0;
Selim Cineka5e211b2014-08-11 17:35:48 +0200462 mWasReset = true;
Selim Cinek31094df2014-08-14 19:28:15 +0200463 onHeightReset();
Selim Cinek6e28a672014-09-05 14:43:28 +0200464 requestLayout();
Christoph Studera7fe6312014-06-27 19:32:44 +0200465 }
466
Jorim Jaggi251957d2014-04-09 04:24:09 +0200467 @Override
Selim Cinek1a521f32014-11-03 17:39:29 +0100468 protected boolean filterMotionEvent(MotionEvent event) {
469 return mIsHeadsUp || super.filterMotionEvent(event);
470 }
471
472 @Override
Jorim Jaggi251957d2014-04-09 04:24:09 +0200473 protected void onFinishInflate() {
474 super.onFinishInflate();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200475 mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
476 mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800477 mPrivateLayout.setExpandClickListener(mExpandClickListener);
478 mPublicLayout.setExpandClickListener(mExpandClickListener);
Selim Cinekab29aeb2015-02-20 18:18:32 +0100479 mGutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
480 mGutsStub.setOnInflateListener(new ViewStub.OnInflateListener() {
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200481 @Override
482 public void onInflate(ViewStub stub, View inflated) {
483 mGuts = (NotificationGuts) inflated;
484 mGuts.setClipTopAmount(getClipTopAmount());
485 mGuts.setActualHeight(getActualHeight());
Selim Cinekab29aeb2015-02-20 18:18:32 +0100486 mGutsStub = null;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200487 }
488 });
Selim Cinekb5605e52015-02-20 18:21:41 +0100489 mChildrenContainerStub = (ViewStub) findViewById(R.id.child_container_stub);
490 mChildrenContainerStub.setOnInflateListener(new ViewStub.OnInflateListener() {
491
492 @Override
493 public void onInflate(ViewStub stub, View inflated) {
494 mChildrenContainer = (NotificationChildrenContainer) inflated;
Selim Cinek388df6d2015-10-22 13:25:11 -0700495 mChildrenContainer.setNotificationParent(ExpandableNotificationRow.this);
Selim Cinekb5605e52015-02-20 18:21:41 +0100496 }
497 });
Selim Cinek863834b2014-05-20 04:20:25 +0200498 mVetoButton = findViewById(R.id.veto);
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200499 }
500
Selim Cinekab29aeb2015-02-20 18:18:32 +0100501 public void inflateGuts() {
502 if (mGuts == null) {
503 mGutsStub.inflate();
504 }
505 }
506
Selim Cinekb5605e52015-02-20 18:21:41 +0100507 private void updateChildrenVisibility(boolean animated) {
508 if (mChildrenContainer == null) {
509 return;
510 }
Selim Cinekeef84282015-10-30 16:28:00 -0700511 mChildrenContainer.setVisibility(mIsSummaryWithChildren ? VISIBLE : INVISIBLE);
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800512 mNotificationHeader.setVisibility(mIsSummaryWithChildren ? VISIBLE : INVISIBLE);
Selim Cinekeef84282015-10-30 16:28:00 -0700513 mPrivateLayout.setVisibility(!mIsSummaryWithChildren ? VISIBLE : INVISIBLE);
Selim Cinekb5605e52015-02-20 18:21:41 +0100514 }
515
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200516 @Override
Alan Viverettea54956a2015-01-07 16:05:02 -0800517 public boolean onRequestSendAccessibilityEventInternal(View child, AccessibilityEvent event) {
518 if (super.onRequestSendAccessibilityEventInternal(child, event)) {
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200519 // Add a record for the entire layout since its content is somehow small.
520 // The event comes from a leaf view that is interacted with.
521 AccessibilityEvent record = AccessibilityEvent.obtain();
522 onInitializeAccessibilityEvent(record);
523 dispatchPopulateAccessibilityEvent(record);
524 event.appendRecord(record);
525 return true;
526 }
527 return false;
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200528 }
Chris Wren51c75102013-07-16 20:49:17 -0400529
John Spurlocke15452b2014-08-21 09:44:39 -0400530 @Override
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100531 public void setDark(boolean dark, boolean fade, long delay) {
532 super.setDark(dark, fade, delay);
John Spurlocke15452b2014-08-21 09:44:39 -0400533 final NotificationContentView showing = getShowingLayout();
534 if (showing != null) {
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100535 showing.setDark(dark, fade, delay);
John Spurlocke15452b2014-08-21 09:44:39 -0400536 }
537 }
538
Selim Cinek1685e632014-04-08 02:27:49 +0200539 public void setHeightRange(int rowMinHeight, int rowMaxHeight) {
540 mRowMinHeight = rowMinHeight;
Selim Cinek379ff8f2015-02-20 17:03:16 +0100541 mMaxViewHeight = rowMaxHeight;
Selim Cinek816c8e42015-11-19 12:00:45 -0800542 mPrivateLayout.setSmallHeight(mRowMinHeight);
543 mPublicLayout.setSmallHeight(mRowMinHeight);
Chris Wren51c75102013-07-16 20:49:17 -0400544 }
545
546 public boolean isExpandable() {
Selim Cinek388df6d2015-10-22 13:25:11 -0700547 if (mIsSummaryWithChildren && !mShowingPublic) {
548 return !mChildrenExpanded;
549 }
Chris Wren51c75102013-07-16 20:49:17 -0400550 return mExpandable;
551 }
552
553 public void setExpandable(boolean expandable) {
554 mExpandable = expandable;
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800555 mPrivateLayout.updateExpandButtons(isExpandable());
Chris Wren51c75102013-07-16 20:49:17 -0400556 }
557
Selim Cinek1685e632014-04-08 02:27:49 +0200558 /**
559 * @return whether the user has changed the expansion state
560 */
561 public boolean hasUserChangedExpansion() {
562 return mHasUserChangedExpansion;
563 }
564
Chris Wren51c75102013-07-16 20:49:17 -0400565 public boolean isUserExpanded() {
566 return mUserExpanded;
567 }
568
Selim Cinek1685e632014-04-08 02:27:49 +0200569 /**
570 * Set this notification to be expanded by the user
571 *
572 * @param userExpanded whether the user wants this notification to be expanded
573 */
Chris Wren51c75102013-07-16 20:49:17 -0400574 public void setUserExpanded(boolean userExpanded) {
Selim Cinek388df6d2015-10-22 13:25:11 -0700575 setUserExpanded(userExpanded, false /* allowChildExpansion */);
576 }
577
578 /**
579 * Set this notification to be expanded by the user
580 *
581 * @param userExpanded whether the user wants this notification to be expanded
582 * @param allowChildExpansion whether a call to this method allows expanding children
583 */
584 public void setUserExpanded(boolean userExpanded, boolean allowChildExpansion) {
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700585 mFalsingManager.setNotificationExpanded();
Selim Cinek388df6d2015-10-22 13:25:11 -0700586 if (mIsSummaryWithChildren && !mShowingPublic && allowChildExpansion) {
587 mGroupManager.setGroupExpanded(mStatusBarNotification, userExpanded);
588 return;
589 }
Christoph Studera7fe6312014-06-27 19:32:44 +0200590 if (userExpanded && !mExpandable) return;
Chris Wren78403d72014-07-28 10:23:24 +0100591 final boolean wasExpanded = isExpanded();
Selim Cinek1685e632014-04-08 02:27:49 +0200592 mHasUserChangedExpansion = true;
Chris Wren51c75102013-07-16 20:49:17 -0400593 mUserExpanded = userExpanded;
Chris Wren78403d72014-07-28 10:23:24 +0100594 logExpansionEvent(true, wasExpanded);
Chris Wren51c75102013-07-16 20:49:17 -0400595 }
596
Selim Cinekccd14fb2014-08-12 18:53:24 +0200597 public void resetUserExpansion() {
598 mHasUserChangedExpansion = false;
599 mUserExpanded = false;
600 }
601
Chris Wren51c75102013-07-16 20:49:17 -0400602 public boolean isUserLocked() {
603 return mUserLocked;
604 }
605
606 public void setUserLocked(boolean userLocked) {
607 mUserLocked = userLocked;
608 }
609
Selim Cinek1685e632014-04-08 02:27:49 +0200610 /**
611 * @return has the system set this notification to be expanded
612 */
613 public boolean isSystemExpanded() {
614 return mIsSystemExpanded;
615 }
616
617 /**
618 * Set this notification to be expanded by the system.
619 *
620 * @param expand whether the system wants this notification to be expanded.
621 */
622 public void setSystemExpanded(boolean expand) {
Selim Cinek31094df2014-08-14 19:28:15 +0200623 if (expand != mIsSystemExpanded) {
624 final boolean wasExpanded = isExpanded();
625 mIsSystemExpanded = expand;
Selim Cinekb5605e52015-02-20 18:21:41 +0100626 notifyHeightChanged(false /* needsAnimation */);
Selim Cinek31094df2014-08-14 19:28:15 +0200627 logExpansionEvent(false, wasExpanded);
Selim Cinek83bc7832015-10-22 13:26:54 -0700628 if (mChildrenContainer != null) {
629 mChildrenContainer.updateGroupOverflow();
630 }
Selim Cinek31094df2014-08-14 19:28:15 +0200631 }
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200632 }
633
634 /**
Selim Cinek83bc7832015-10-22 13:26:54 -0700635 * @param onKeyguard whether to prevent notification expansion
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200636 */
Selim Cinek83bc7832015-10-22 13:26:54 -0700637 public void setOnKeyguard(boolean onKeyguard) {
638 if (onKeyguard != mOnKeyguard) {
Selim Cinek31094df2014-08-14 19:28:15 +0200639 final boolean wasExpanded = isExpanded();
Selim Cinek83bc7832015-10-22 13:26:54 -0700640 mOnKeyguard = onKeyguard;
Selim Cinek31094df2014-08-14 19:28:15 +0200641 logExpansionEvent(false, wasExpanded);
642 if (wasExpanded != isExpanded()) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100643 notifyHeightChanged(false /* needsAnimation */);
Selim Cinek31094df2014-08-14 19:28:15 +0200644 }
645 }
Selim Cinek1685e632014-04-08 02:27:49 +0200646 }
647
648 /**
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400649 * @return Can the underlying notification be cleared?
650 */
651 public boolean isClearable() {
Selim Cineka37774f2014-11-11 19:16:18 +0100652 return mStatusBarNotification != null && mStatusBarNotification.isClearable();
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400653 }
654
655 /**
Selim Cinek1685e632014-04-08 02:27:49 +0200656 * Apply an expansion state to the layout.
Selim Cinek1685e632014-04-08 02:27:49 +0200657 */
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200658 public void applyExpansionToLayout() {
659 boolean expand = isExpanded();
Chris Wren51c75102013-07-16 20:49:17 -0400660 if (expand && mExpandable) {
Selim Cinekeef84282015-10-30 16:28:00 -0700661 setActualHeight(mMaxExpandHeight);
Chris Wren51c75102013-07-16 20:49:17 -0400662 } else {
Selim Cinekeef84282015-10-30 16:28:00 -0700663 setActualHeight(mRowMinHeight);
Chris Wren51c75102013-07-16 20:49:17 -0400664 }
Chris Wren51c75102013-07-16 20:49:17 -0400665 }
Dan Sandlera5e0f412014-01-23 15:11:54 -0500666
Jorim Jaggi9cbadd32014-05-01 20:18:31 +0200667 @Override
668 public int getIntrinsicHeight() {
Jorim Jaggibe565df2014-04-28 17:51:23 +0200669 if (isUserLocked()) {
670 return getActualHeight();
671 }
Selim Cinek1685e632014-04-08 02:27:49 +0200672 boolean inExpansionState = isExpanded();
Selim Cinek60122be2015-04-15 18:16:50 -0700673 if (mSensitive && mHideSensitiveForIntrinsicHeight) {
674 return mRowMinHeight;
Selim Cinek83bc7832015-10-22 13:26:54 -0700675 } else if (mIsSummaryWithChildren && !mOnKeyguard) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800676 return mChildrenContainer.getIntrinsicHeight();
Selim Cinek60122be2015-04-15 18:16:50 -0700677 } else if (mIsHeadsUp) {
Selim Cinek8d490d42015-04-10 00:05:50 -0700678 if (inExpansionState) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700679 return Math.max(mMaxExpandHeight, mHeadsUpHeight);
Selim Cinek8d490d42015-04-10 00:05:50 -0700680 } else {
Selim Cinek83bc7832015-10-22 13:26:54 -0700681 return Math.max(mRowMinHeight, mHeadsUpHeight);
Selim Cinek8d490d42015-04-10 00:05:50 -0700682 }
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700683 } else if (!inExpansionState || (isChildInGroup() && !isGroupExpanded())) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700684 return getMinHeight();
Selim Cinekb5605e52015-02-20 18:21:41 +0100685 } else {
Selim Cinek83bc7832015-10-22 13:26:54 -0700686 return getMaxExpandHeight();
Selim Cinek1685e632014-04-08 02:27:49 +0200687 }
Selim Cinekb5605e52015-02-20 18:21:41 +0100688 }
Selim Cinek1685e632014-04-08 02:27:49 +0200689
Selim Cinekeef84282015-10-30 16:28:00 -0700690 private boolean isGroupExpanded() {
691 return mGroupManager.isGroupExpanded(mStatusBarNotification);
Selim Cinekb5605e52015-02-20 18:21:41 +0100692 }
693
Selim Cinekeef84282015-10-30 16:28:00 -0700694 /**
695 * @return whether this view has a header on the top of the content
696 */
697 private boolean hasNotificationHeader() {
698 return mIsSummaryWithChildren;
Selim Cinek1685e632014-04-08 02:27:49 +0200699 }
700
Selim Cinek263398f2015-10-21 17:40:23 -0700701 private void onChildrenCountChanged() {
Selim Cinek8fc93c92015-11-23 17:48:07 -0800702 mIsSummaryWithChildren = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS
Selim Cinek263398f2015-10-21 17:40:23 -0700703 && mGroupManager.hasGroupChildren(mStatusBarNotification);
Selim Cinek8fc93c92015-11-23 17:48:07 -0800704 if (mIsSummaryWithChildren) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800705 if (mChildrenContainer == null) {
706 mChildrenContainerStub.inflate();
707 }
Selim Cinek8fc93c92015-11-23 17:48:07 -0800708 if (mNotificationHeader == null) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800709 recreateNotificationHeader();
710 }
Selim Cinek263398f2015-10-21 17:40:23 -0700711 }
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800712 mPrivateLayout.updateExpandButtons(isExpandable());
713 updateHeaderChildCount();
Selim Cinek263398f2015-10-21 17:40:23 -0700714 updateChildrenVisibility(true);
715 }
716
Selim Cinek1685e632014-04-08 02:27:49 +0200717 /**
718 * Check whether the view state is currently expanded. This is given by the system in {@link
719 * #setSystemExpanded(boolean)} and can be overridden by user expansion or
720 * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this
721 * view can differ from this state, if layout params are modified from outside.
722 *
723 * @return whether the view state is currently expanded.
724 */
Selim Cinek83bc7832015-10-22 13:26:54 -0700725 public boolean isExpanded() {
726 return !mOnKeyguard
Selim Cinekb5605e52015-02-20 18:21:41 +0100727 && (!hasUserChangedExpansion() && (isSystemExpanded() || isSystemChildExpanded())
728 || isUserExpanded());
729 }
730
731 private boolean isSystemChildExpanded() {
732 return mIsSystemChildExpanded;
733 }
734
735 public void setSystemChildExpanded(boolean expanded) {
736 mIsSystemChildExpanded = expanded;
Selim Cinek1685e632014-04-08 02:27:49 +0200737 }
738
739 @Override
740 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
741 super.onLayout(changed, left, top, right, bottom);
Selim Cineka5e211b2014-08-11 17:35:48 +0200742 boolean updateExpandHeight = mMaxExpandHeight == 0 && !mWasReset;
Selim Cinek8d490d42015-04-10 00:05:50 -0700743 updateMaxHeights();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200744 if (updateExpandHeight) {
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200745 applyExpansionToLayout();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200746 }
Selim Cineka5e211b2014-08-11 17:35:48 +0200747 mWasReset = false;
Selim Cinek1685e632014-04-08 02:27:49 +0200748 }
749
Selim Cinek8d490d42015-04-10 00:05:50 -0700750 private void updateMaxHeights() {
Selim Cinekd2319fb2014-09-01 19:41:54 +0200751 int intrinsicBefore = getIntrinsicHeight();
Selim Cinek8d490d42015-04-10 00:05:50 -0700752 View expandedChild = mPrivateLayout.getExpandedChild();
753 if (expandedChild == null) {
754 expandedChild = mPrivateLayout.getContractedChild();
755 }
756 mMaxExpandHeight = expandedChild.getHeight();
757 View headsUpChild = mPrivateLayout.getHeadsUpChild();
Selim Cinek1f3f5442015-04-10 17:54:46 -0700758 if (headsUpChild == null) {
759 headsUpChild = mPrivateLayout.getContractedChild();
Selim Cinek8d490d42015-04-10 00:05:50 -0700760 }
Selim Cinek1f3f5442015-04-10 17:54:46 -0700761 mHeadsUpHeight = headsUpChild.getHeight();
Selim Cinekd2319fb2014-09-01 19:41:54 +0200762 if (intrinsicBefore != getIntrinsicHeight()) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100763 notifyHeightChanged(false /* needsAnimation */);
Selim Cinekd2319fb2014-09-01 19:41:54 +0200764 }
765 }
766
Jorim Jaggiae441282014-08-01 02:45:18 +0200767 public void setSensitive(boolean sensitive) {
768 mSensitive = sensitive;
769 }
770
771 public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) {
Selim Cinek60122be2015-04-15 18:16:50 -0700772 mHideSensitiveForIntrinsicHeight = hideSensitive;
Jorim Jaggiae441282014-08-01 02:45:18 +0200773 }
774
775 public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
776 long duration) {
777 boolean oldShowingPublic = mShowingPublic;
778 mShowingPublic = mSensitive && hideSensitive;
779 if (mShowingPublicInitialized && mShowingPublic == oldShowingPublic) {
780 return;
781 }
Dan Sandlera5e0f412014-01-23 15:11:54 -0500782
783 // bail out if no public version
Selim Cinek1685e632014-04-08 02:27:49 +0200784 if (mPublicLayout.getChildCount() == 0) return;
Dan Sandlera5e0f412014-01-23 15:11:54 -0500785
Jorim Jaggiae441282014-08-01 02:45:18 +0200786 if (!animated) {
787 mPublicLayout.animate().cancel();
788 mPrivateLayout.animate().cancel();
789 mPublicLayout.setAlpha(1f);
790 mPrivateLayout.setAlpha(1f);
791 mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE);
Selim Cinek263398f2015-10-21 17:40:23 -0700792 mPrivateLayout.setVisibility(!mShowingPublic && !mIsSummaryWithChildren ? View.VISIBLE
793 : View.INVISIBLE);
Jorim Jaggiae441282014-08-01 02:45:18 +0200794 } else {
795 animateShowingPublic(delay, duration);
796 }
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400797
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800798 mPrivateLayout.updateExpandButtons(isExpandable());
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400799 updateVetoButton();
Jorim Jaggiae441282014-08-01 02:45:18 +0200800 mShowingPublicInitialized = true;
801 }
802
803 private void animateShowingPublic(long delay, long duration) {
804 final View source = mShowingPublic ? mPrivateLayout : mPublicLayout;
805 View target = mShowingPublic ? mPublicLayout : mPrivateLayout;
806 source.setVisibility(View.VISIBLE);
807 target.setVisibility(View.VISIBLE);
808 target.setAlpha(0f);
809 source.animate().cancel();
810 target.animate().cancel();
811 source.animate()
812 .alpha(0f)
Jorim Jaggiae441282014-08-01 02:45:18 +0200813 .setStartDelay(delay)
814 .setDuration(duration)
815 .withEndAction(new Runnable() {
816 @Override
817 public void run() {
818 source.setVisibility(View.INVISIBLE);
819 }
820 });
821 target.animate()
822 .alpha(1f)
Jorim Jaggiae441282014-08-01 02:45:18 +0200823 .setStartDelay(delay)
824 .setDuration(duration);
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400825 }
826
827 private void updateVetoButton() {
828 // public versions cannot be dismissed
829 mVetoButton.setVisibility(isClearable() && !mShowingPublic ? View.VISIBLE : View.GONE);
Dan Sandlera5e0f412014-01-23 15:11:54 -0500830 }
Jorim Jaggi251957d2014-04-09 04:24:09 +0200831
Selim Cinekb5605e52015-02-20 18:21:41 +0100832 public void setChildrenExpanded(boolean expanded, boolean animate) {
833 mChildrenExpanded = expanded;
Selim Cinek83bc7832015-10-22 13:26:54 -0700834 if (mChildrenContainer != null) {
835 mChildrenContainer.setChildrenExpanded(expanded);
836 }
Selim Cinekb5605e52015-02-20 18:21:41 +0100837 }
838
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800839 public void updateHeaderChildCount() {
840 if (mIsSummaryWithChildren) {
841 mNotificationHeader.setChildCount(
842 mChildrenContainer.getNotificationChildren().size());
Selim Cinekb5605e52015-02-20 18:21:41 +0100843 }
Selim Cinekb5605e52015-02-20 18:21:41 +0100844 }
845
846 public static void applyTint(View v, int color) {
847 int alpha;
848 if (color != 0) {
849 alpha = COLORED_DIVIDER_ALPHA;
850 } else {
851 color = 0xff000000;
852 alpha = DEFAULT_DIVIDER_ALPHA;
853 }
854 if (v.getBackground() instanceof ColorDrawable) {
855 ColorDrawable background = (ColorDrawable) v.getBackground();
856 background.mutate();
857 background.setColor(color);
858 background.setAlpha(alpha);
859 }
860 }
861
Selim Cinek1685e632014-04-08 02:27:49 +0200862 public int getMaxExpandHeight() {
Selim Cinekb5605e52015-02-20 18:21:41 +0100863 return mMaxExpandHeight;
Chris Wren51c75102013-07-16 20:49:17 -0400864 }
Jorim Jaggi584a7aa2014-04-10 23:26:13 +0200865
Jorim Jaggibe565df2014-04-28 17:51:23 +0200866 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200867 public boolean isContentExpandable() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200868 NotificationContentView showingLayout = getShowingLayout();
869 return showingLayout.isContentExpandable();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200870 }
871
872 @Override
Selim Cinek560e64d2015-06-09 19:58:11 -0700873 protected View getContentView() {
874 return getShowingLayout();
875 }
876
877 @Override
Jorim Jaggid552d9d2014-05-07 19:41:13 +0200878 public void setActualHeight(int height, boolean notifyListeners) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100879 super.setActualHeight(height, notifyListeners);
Selim Cinekeef84282015-10-30 16:28:00 -0700880 int contentHeight = Math.max(getMinHeight(), height);
Selim Cinekb5605e52015-02-20 18:21:41 +0100881 mPrivateLayout.setContentHeight(contentHeight);
882 mPublicLayout.setContentHeight(contentHeight);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200883 if (mGuts != null) {
884 mGuts.setActualHeight(height);
885 }
Jorim Jaggibe565df2014-04-28 17:51:23 +0200886 invalidate();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200887 }
888
889 @Override
Selim Cinekb5605e52015-02-20 18:21:41 +0100890 public int getMaxContentHeight() {
Selim Cinek83bc7832015-10-22 13:26:54 -0700891 if (mIsSummaryWithChildren && !mShowingPublic) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800892 return mChildrenContainer.getMaxContentHeight();
Selim Cinek83bc7832015-10-22 13:26:54 -0700893 }
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200894 NotificationContentView showingLayout = getShowingLayout();
895 return showingLayout.getMaxHeight();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200896 }
897
898 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200899 public int getMinHeight() {
Selim Cinek816c8e42015-11-19 12:00:45 -0800900 NotificationContentView showingLayout = getShowingLayout();
901 return showingLayout.getMinHeight();
902 }
903
904 @Override
905 public int getMinExpandHeight() {
Selim Cinek83bc7832015-10-22 13:26:54 -0700906 if (mIsSummaryWithChildren && !mOnKeyguard) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800907 return mChildrenContainer.getMinHeight();
Selim Cinek83bc7832015-10-22 13:26:54 -0700908 }
Selim Cinek816c8e42015-11-19 12:00:45 -0800909 return getMinHeight();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200910 }
911
912 @Override
Selim Cinek263398f2015-10-21 17:40:23 -0700913 protected boolean shouldLimitViewHeight() {
914 return !mIsSummaryWithChildren;
915 }
916
917 @Override
Jorim Jaggibe565df2014-04-28 17:51:23 +0200918 public void setClipTopAmount(int clipTopAmount) {
919 super.setClipTopAmount(clipTopAmount);
920 mPrivateLayout.setClipTopAmount(clipTopAmount);
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200921 mPublicLayout.setClipTopAmount(clipTopAmount);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200922 if (mGuts != null) {
923 mGuts.setClipTopAmount(clipTopAmount);
924 }
Jorim Jaggibe565df2014-04-28 17:51:23 +0200925 }
926
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800927 private void recreateNotificationHeader() {
928 final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
929 getStatusBarNotification().getNotification());
930 final RemoteViews header = builder.makeNotificationHeader();
931 if (mNotificationHeader == null) {
932 mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this);
933 final View expandButton = mNotificationHeader.findViewById(
934 com.android.internal.R.id.expand_button);
935 expandButton.setVisibility(VISIBLE);
936 mNotificationHeader.setOnClickListener(mExpandClickListener);
937 addView(mNotificationHeader);
938 } else {
939 header.reapply(getContext(), mNotificationHeader);
940 }
Selim Cinek8fc93c92015-11-23 17:48:07 -0800941 updateHeaderChildCount();
Selim Cinek343e6e22014-04-11 21:23:30 +0200942 }
Selim Cinek7d447722014-06-10 15:51:59 +0200943
Selim Cinek31094df2014-08-14 19:28:15 +0200944 public boolean isMaxExpandHeightInitialized() {
945 return mMaxExpandHeight != 0;
Selim Cinek7d447722014-06-10 15:51:59 +0200946 }
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200947
948 private NotificationContentView getShowingLayout() {
949 return mShowingPublic ? mPublicLayout : mPrivateLayout;
950 }
Chris Wren78403d72014-07-28 10:23:24 +0100951
Jorim Jaggi59ec3042015-06-05 15:18:43 -0700952 @Override
953 public void setShowingLegacyBackground(boolean showing) {
954 super.setShowingLegacyBackground(showing);
955 mPrivateLayout.setShowingLegacyBackground(showing);
956 mPublicLayout.setShowingLegacyBackground(showing);
957 }
958
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700959 @Override
960 protected void updateBackgroundTint() {
961 super.updateBackgroundTint();
962 updateNoBackgroundState();
963 if (mIsSummaryWithChildren) {
964 List<ExpandableNotificationRow> notificationChildren =
965 mChildrenContainer.getNotificationChildren();
966 for (int i = 0; i < notificationChildren.size(); i++) {
967 ExpandableNotificationRow child = notificationChildren.get(i);
968 child.updateNoBackgroundState();
969 }
970 }
971 }
972
973 private void updateNoBackgroundState() {
974 mShowNoBackground = isChildInGroup() && hasSameBgColor(mNotificationParent);
975 updateBackground();
976 }
977
Chris Wren78403d72014-07-28 10:23:24 +0100978 public void setExpansionLogger(ExpansionLogger logger, String key) {
979 mLogger = logger;
980 mLoggingKey = key;
981 }
982
Chris Wren78403d72014-07-28 10:23:24 +0100983 private void logExpansionEvent(boolean userAction, boolean wasExpanded) {
984 final boolean nowExpanded = isExpanded();
985 if (wasExpanded != nowExpanded && mLogger != null) {
986 mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded) ;
987 }
988 }
Chris Wren51c75102013-07-16 20:49:17 -0400989}