blob: c73e115d9dd00ad199b925753e5430107b83ded9 [file] [log] [blame]
Chris Wren51c75102013-07-16 20:49:17 -04001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.statusbar;
18
Mady Mellor4b80b102016-01-22 08:03:58 -080019import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
21import android.animation.AnimatorSet;
22import android.animation.ObjectAnimator;
23import android.animation.ValueAnimator;
24import android.animation.ValueAnimator.AnimatorUpdateListener;
Selim Cineka6c6bfb2015-10-29 16:27:08 -070025import android.app.Notification;
Chris Wren51c75102013-07-16 20:49:17 -040026import android.content.Context;
Selim Cinekcab4a602014-09-03 14:47:57 +020027import android.graphics.drawable.AnimatedVectorDrawable;
28import android.graphics.drawable.AnimationDrawable;
Selim Cinekb5605e52015-02-20 18:21:41 +010029import android.graphics.drawable.ColorDrawable;
Selim Cinekcab4a602014-09-03 14:47:57 +020030import android.graphics.drawable.Drawable;
Selim Cinekda42d652015-12-04 15:51:16 -080031import android.os.Build;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +020032import android.service.notification.StatusBarNotification;
Chris Wren51c75102013-07-16 20:49:17 -040033import android.util.AttributeSet;
Selim Cinek01af3342016-02-09 19:25:31 -080034import android.view.LayoutInflater;
Selim Cinek6183d122016-01-14 18:48:41 -080035import android.view.MotionEvent;
Selim Cinekeaa29ca2015-11-23 13:51:13 -080036import android.view.NotificationHeaderView;
Dan Sandlera5e0f412014-01-23 15:11:54 -050037import android.view.View;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +020038import android.view.ViewStub;
Jorim Jaggife40f7d2014-04-28 15:20:04 +020039import android.view.accessibility.AccessibilityEvent;
Selim Cinek98713a42015-09-21 15:47:20 +020040import android.widget.Chronometer;
Selim Cinekcab4a602014-09-03 14:47:57 +020041import android.widget.ImageView;
Selim Cinekeaa29ca2015-11-23 13:51:13 -080042import android.widget.RemoteViews;
Selim Cinekb5605e52015-02-20 18:21:41 +010043
Dan Sandlera5e0f412014-01-23 15:11:54 -050044import com.android.systemui.R;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -070045import com.android.systemui.classifier.FalsingManager;
Selim Cinek0ffbda62016-01-01 20:29:12 +010046import com.android.systemui.statusbar.notification.NotificationViewWrapper;
Selim Cinekb5605e52015-02-20 18:21:41 +010047import com.android.systemui.statusbar.phone.NotificationGroupManager;
Selim Cinek31aada42015-12-18 17:51:15 -080048import com.android.systemui.statusbar.policy.HeadsUpManager;
Selim Cinekb5605e52015-02-20 18:21:41 +010049import com.android.systemui.statusbar.stack.NotificationChildrenContainer;
50import com.android.systemui.statusbar.stack.StackScrollState;
51import com.android.systemui.statusbar.stack.StackStateAnimator;
52import com.android.systemui.statusbar.stack.StackViewState;
53
Mady Mellor4b80b102016-01-22 08:03:58 -080054import java.util.ArrayList;
Selim Cinekb5605e52015-02-20 18:21:41 +010055import java.util.List;
Dan Sandlera5e0f412014-01-23 15:11:54 -050056
Jorim Jaggi4222d9a2014-04-23 16:13:15 +020057public class ExpandableNotificationRow extends ActivatableNotificationView {
Selim Cinekb5605e52015-02-20 18:21:41 +010058
59 private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
60 private static final int COLORED_DIVIDER_ALPHA = 0x7B;
Selim Cinek01af3342016-02-09 19:25:31 -080061 private int mNotificationMinHeightLegacy;
62 private int mMaxHeadsUpHeightLegacy;
63 private int mMaxHeadsUpHeight;
64 private int mNotificationMinHeight;
65 private int mNotificationMaxHeight;
Chris Wren51c75102013-07-16 20:49:17 -040066
Selim Cinek1685e632014-04-08 02:27:49 +020067 /** Does this row contain layouts that can adapt to row expansion */
Chris Wren51c75102013-07-16 20:49:17 -040068 private boolean mExpandable;
Selim Cinek1685e632014-04-08 02:27:49 +020069 /** Has the user actively changed the expansion state of this row */
70 private boolean mHasUserChangedExpansion;
71 /** If {@link #mHasUserChangedExpansion}, has the user expanded this row */
Chris Wren51c75102013-07-16 20:49:17 -040072 private boolean mUserExpanded;
Selim Cinek31aada42015-12-18 17:51:15 -080073
74 /**
75 * Has this notification been expanded while it was pinned
76 */
77 private boolean mExpandedWhenPinned;
Selim Cinek1685e632014-04-08 02:27:49 +020078 /** Is the user touching this row */
Chris Wren51c75102013-07-16 20:49:17 -040079 private boolean mUserLocked;
Selim Cinek1685e632014-04-08 02:27:49 +020080 /** Are we showing the "public" version */
Dan Sandlera5e0f412014-01-23 15:11:54 -050081 private boolean mShowingPublic;
Jorim Jaggiae441282014-08-01 02:45:18 +020082 private boolean mSensitive;
83 private boolean mShowingPublicInitialized;
Selim Cinek60122be2015-04-15 18:16:50 -070084 private boolean mHideSensitiveForIntrinsicHeight;
Chris Wren51c75102013-07-16 20:49:17 -040085
Selim Cinek1685e632014-04-08 02:27:49 +020086 /**
87 * Is this notification expanded by the system. The expansion state can be overridden by the
88 * user expansion.
89 */
90 private boolean mIsSystemExpanded;
Jorim Jaggidce3c4c2014-04-29 23:12:24 +020091
92 /**
Selim Cinek83bc7832015-10-22 13:26:54 -070093 * Whether the notification is on the keyguard and the expansion is disabled.
Jorim Jaggidce3c4c2014-04-29 23:12:24 +020094 */
Selim Cinek83bc7832015-10-22 13:26:54 -070095 private boolean mOnKeyguard;
Jorim Jaggidce3c4c2014-04-29 23:12:24 +020096
Mady Mellor4b80b102016-01-22 08:03:58 -080097 private AnimatorSet mTranslateAnim;
98 private ArrayList<View> mTranslateableViews;
Jorim Jaggibe565df2014-04-28 17:51:23 +020099 private NotificationContentView mPublicLayout;
100 private NotificationContentView mPrivateLayout;
Selim Cinek1685e632014-04-08 02:27:49 +0200101 private int mMaxExpandHeight;
Selim Cinek8d490d42015-04-10 00:05:50 -0700102 private int mHeadsUpHeight;
Selim Cinek863834b2014-05-20 04:20:25 +0200103 private View mVetoButton;
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400104 private boolean mClearable;
Chris Wren78403d72014-07-28 10:23:24 +0100105 private ExpansionLogger mLogger;
106 private String mLoggingKey;
Selim Cineka5e211b2014-08-11 17:35:48 +0200107 private boolean mWasReset;
Mady Mellor4b80b102016-01-22 08:03:58 -0800108 private NotificationSettingsIconRow mSettingsIconRow;
Selim Cinek8d490d42015-04-10 00:05:50 -0700109 private NotificationGuts mGuts;
Selim Cinekda42d652015-12-04 15:51:16 -0800110 private NotificationData.Entry mEntry;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200111 private StatusBarNotification mStatusBarNotification;
Selim Cinek1a521f32014-11-03 17:39:29 +0100112 private boolean mIsHeadsUp;
Selim Cinek98713a42015-09-21 15:47:20 +0200113 private boolean mLastChronometerRunning = true;
Selim Cinekeef84282015-10-30 16:28:00 -0700114 private NotificationHeaderView mNotificationHeader;
Selim Cinek9c7712d2015-12-08 19:19:48 -0800115 private NotificationViewWrapper mNotificationHeaderWrapper;
Selim Cinekb5605e52015-02-20 18:21:41 +0100116 private ViewStub mChildrenContainerStub;
117 private NotificationGroupManager mGroupManager;
Selim Cinekb5605e52015-02-20 18:21:41 +0100118 private boolean mChildrenExpanded;
Selim Cinek263398f2015-10-21 17:40:23 -0700119 private boolean mIsSummaryWithChildren;
Selim Cinekb5605e52015-02-20 18:21:41 +0100120 private NotificationChildrenContainer mChildrenContainer;
Mady Mellor4b80b102016-01-22 08:03:58 -0800121 private ViewStub mSettingsIconRowStub;
Selim Cinekab29aeb2015-02-20 18:18:32 +0100122 private ViewStub mGutsStub;
Selim Cinekb5605e52015-02-20 18:21:41 +0100123 private boolean mIsSystemChildExpanded;
Selim Cinek684a4422015-04-15 16:18:39 -0700124 private boolean mIsPinned;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700125 private FalsingManager mFalsingManager;
Selim Cinek31aada42015-12-18 17:51:15 -0800126 private HeadsUpManager mHeadsUpManager;
Selim Cinekea4bef72015-12-02 15:51:10 -0800127 private NotificationHeaderUtil mHeaderUtil = new NotificationHeaderUtil(this);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200128
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700129 private boolean mJustClicked;
Selim Cinek5a175d92015-11-23 18:01:33 -0800130 private boolean mIconAnimationRunning;
Selim Cinek34d93b02015-10-22 12:30:38 -0700131 private boolean mShowNoBackground;
Selim Cinek388df6d2015-10-22 13:25:11 -0700132 private ExpandableNotificationRow mNotificationParent;
Selim Cinek570981d2015-12-01 11:37:01 -0800133 private OnExpandClickListener mOnExpandClickListener;
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800134 private OnClickListener mExpandClickListener = new OnClickListener() {
135 @Override
136 public void onClick(View v) {
Selim Cinek624c02db2015-12-14 21:00:02 -0800137 if (!mShowingPublic && mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800138 mGroupManager.toggleGroupExpansion(mStatusBarNotification);
Selim Cinek31aada42015-12-18 17:51:15 -0800139 mOnExpandClickListener.onExpandClicked(mEntry,
Selim Cinek570981d2015-12-01 11:37:01 -0800140 mGroupManager.isGroupExpanded(mStatusBarNotification));
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800141 } else {
Selim Cinek31aada42015-12-18 17:51:15 -0800142 boolean nowExpanded;
143 if (isPinned()) {
144 nowExpanded = !mExpandedWhenPinned;
145 mExpandedWhenPinned = nowExpanded;
146 } else {
147 nowExpanded = !isExpanded();
148 setUserExpanded(nowExpanded);
149 }
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800150 notifyHeightChanged(true);
Selim Cinek31aada42015-12-18 17:51:15 -0800151 mOnExpandClickListener.onExpandClicked(mEntry, nowExpanded);
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800152 }
153 }
154 };
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700155
Selim Cinek8d490d42015-04-10 00:05:50 -0700156 public NotificationContentView getPrivateLayout() {
157 return mPrivateLayout;
158 }
159
160 public NotificationContentView getPublicLayout() {
161 return mPublicLayout;
162 }
163
Selim Cinekcab4a602014-09-03 14:47:57 +0200164 public void setIconAnimationRunning(boolean running) {
165 setIconAnimationRunning(running, mPublicLayout);
166 setIconAnimationRunning(running, mPrivateLayout);
Selim Cinek5a175d92015-11-23 18:01:33 -0800167 setIconAnimationRunningForChild(running, mNotificationHeader);
168 if (mIsSummaryWithChildren) {
169 List<ExpandableNotificationRow> notificationChildren =
170 mChildrenContainer.getNotificationChildren();
171 for (int i = 0; i < notificationChildren.size(); i++) {
172 ExpandableNotificationRow child = notificationChildren.get(i);
173 child.setIconAnimationRunning(running);
174 }
175 }
176 mIconAnimationRunning = running;
Selim Cinekcab4a602014-09-03 14:47:57 +0200177 }
178
179 private void setIconAnimationRunning(boolean running, NotificationContentView layout) {
180 if (layout != null) {
181 View contractedChild = layout.getContractedChild();
182 View expandedChild = layout.getExpandedChild();
Selim Cinek8d490d42015-04-10 00:05:50 -0700183 View headsUpChild = layout.getHeadsUpChild();
Selim Cinekcab4a602014-09-03 14:47:57 +0200184 setIconAnimationRunningForChild(running, contractedChild);
185 setIconAnimationRunningForChild(running, expandedChild);
Selim Cinek8d490d42015-04-10 00:05:50 -0700186 setIconAnimationRunningForChild(running, headsUpChild);
Selim Cinekcab4a602014-09-03 14:47:57 +0200187 }
188 }
189
190 private void setIconAnimationRunningForChild(boolean running, View child) {
191 if (child != null) {
192 ImageView icon = (ImageView) child.findViewById(com.android.internal.R.id.icon);
193 setIconRunning(icon, running);
194 ImageView rightIcon = (ImageView) child.findViewById(
195 com.android.internal.R.id.right_icon);
196 setIconRunning(rightIcon, running);
197 }
198 }
199
200 private void setIconRunning(ImageView imageView, boolean running) {
201 if (imageView != null) {
202 Drawable drawable = imageView.getDrawable();
203 if (drawable instanceof AnimationDrawable) {
204 AnimationDrawable animationDrawable = (AnimationDrawable) drawable;
205 if (running) {
206 animationDrawable.start();
207 } else {
208 animationDrawable.stop();
209 }
210 } else if (drawable instanceof AnimatedVectorDrawable) {
211 AnimatedVectorDrawable animationDrawable = (AnimatedVectorDrawable) drawable;
212 if (running) {
213 animationDrawable.start();
214 } else {
215 animationDrawable.stop();
216 }
217 }
218 }
219 }
220
Selim Cinekda42d652015-12-04 15:51:16 -0800221 public void onNotificationUpdated(NotificationData.Entry entry) {
222 mEntry = entry;
223 mStatusBarNotification = entry.notification;
Adrian Roosb88b1a12015-12-09 18:51:05 -0800224 mPrivateLayout.onNotificationUpdated(entry);
225 mPublicLayout.onNotificationUpdated(entry);
Selim Cinek757d8792016-01-28 16:21:08 -0800226 mShowingPublicInitialized = false;
227 updateClearability();
Selim Cinek8fc93c92015-11-23 17:48:07 -0800228 if (mIsSummaryWithChildren) {
229 recreateNotificationHeader();
230 }
Selim Cinek5a175d92015-11-23 18:01:33 -0800231 if (mIconAnimationRunning) {
232 setIconAnimationRunning(true);
233 }
Selim Cinekea4bef72015-12-02 15:51:10 -0800234 if (mNotificationParent != null) {
235 mNotificationParent.updateChildrenHeaderAppearance();
236 }
Selim Cinek263398f2015-10-21 17:40:23 -0700237 onChildrenCountChanged();
Selim Cinek624c02db2015-12-14 21:00:02 -0800238 // The public layouts expand button is always visible
239 mPublicLayout.updateExpandButtons(true);
Selim Cinekda42d652015-12-04 15:51:16 -0800240 updateLimits();
241 }
242
243 private void updateLimits() {
244 boolean customView = getPrivateLayout().getContractedChild().getId()
245 != com.android.internal.R.id.status_bar_latest_event_content;
246 boolean beforeN = mEntry.targetSdk < Build.VERSION_CODES.N;
247 int minHeight = customView && beforeN && !mIsSummaryWithChildren ?
248 mNotificationMinHeightLegacy : mNotificationMinHeight;
Selim Cinek77019c72015-12-09 10:18:02 -0800249 boolean headsUpCustom = getPrivateLayout().getHeadsUpChild() != null &&
250 getPrivateLayout().getHeadsUpChild().getId()
251 != com.android.internal.R.id.status_bar_latest_event_content;
252 int headsUpheight = headsUpCustom && beforeN ? mMaxHeadsUpHeightLegacy
253 : mMaxHeadsUpHeight;
Selim Cinek860b6da2015-12-16 19:02:19 -0800254 mPrivateLayout.setHeights(minHeight, headsUpheight, mNotificationMaxHeight);
255 mPublicLayout.setHeights(minHeight, headsUpheight, mNotificationMaxHeight);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200256 }
257
258 public StatusBarNotification getStatusBarNotification() {
259 return mStatusBarNotification;
260 }
261
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700262 public boolean isHeadsUp() {
263 return mIsHeadsUp;
264 }
265
Selim Cinek1a521f32014-11-03 17:39:29 +0100266 public void setHeadsUp(boolean isHeadsUp) {
Selim Cinekc80fdb12015-04-13 15:09:08 -0700267 int intrinsicBefore = getIntrinsicHeight();
Selim Cinek1a521f32014-11-03 17:39:29 +0100268 mIsHeadsUp = isHeadsUp;
Selim Cinek8d490d42015-04-10 00:05:50 -0700269 mPrivateLayout.setHeadsUp(isHeadsUp);
Selim Cinekc80fdb12015-04-13 15:09:08 -0700270 if (intrinsicBefore != getIntrinsicHeight()) {
271 notifyHeightChanged(false /* needsAnimation */);
272 }
Selim Cinek1a521f32014-11-03 17:39:29 +0100273 }
274
Selim Cinekb5605e52015-02-20 18:21:41 +0100275 public void setGroupManager(NotificationGroupManager groupManager) {
276 mGroupManager = groupManager;
Selim Cinek83bc7832015-10-22 13:26:54 -0700277 mPrivateLayout.setGroupManager(groupManager);
Selim Cinekb5605e52015-02-20 18:21:41 +0100278 }
279
Adrian Roosb88b1a12015-12-09 18:51:05 -0800280 public void setRemoteInputController(RemoteInputController r) {
281 mPrivateLayout.setRemoteInputController(r);
282 }
283
Selim Cinekb5605e52015-02-20 18:21:41 +0100284 public void addChildNotification(ExpandableNotificationRow row) {
285 addChildNotification(row, -1);
286 }
287
288 /**
289 * Add a child notification to this view.
290 *
291 * @param row the row to add
292 * @param childIndex the index to add it at, if -1 it will be added at the end
293 */
294 public void addChildNotification(ExpandableNotificationRow row, int childIndex) {
295 if (mChildrenContainer == null) {
296 mChildrenContainerStub.inflate();
297 }
298 mChildrenContainer.addNotification(row, childIndex);
Selim Cinek263398f2015-10-21 17:40:23 -0700299 onChildrenCountChanged();
300 row.setIsChildInGroup(true, this);
Selim Cinekb5605e52015-02-20 18:21:41 +0100301 }
302
303 public void removeChildNotification(ExpandableNotificationRow row) {
304 if (mChildrenContainer != null) {
305 mChildrenContainer.removeNotification(row);
306 }
Selim Cinekea4bef72015-12-02 15:51:10 -0800307 mHeaderUtil.restoreNotificationHeader(row);
Selim Cinek263398f2015-10-21 17:40:23 -0700308 onChildrenCountChanged();
309 row.setIsChildInGroup(false, null);
310 }
311
312 public boolean isChildInGroup() {
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700313 return mNotificationParent != null;
Selim Cinek263398f2015-10-21 17:40:23 -0700314 }
315
Selim Cinek388df6d2015-10-22 13:25:11 -0700316 public ExpandableNotificationRow getNotificationParent() {
317 return mNotificationParent;
318 }
319
Selim Cinek263398f2015-10-21 17:40:23 -0700320 /**
321 * @param isChildInGroup Is this notification now in a group
322 * @param parent the new parent notification
323 */
Selim Cineka6c6bfb2015-10-29 16:27:08 -0700324 public void setIsChildInGroup(boolean isChildInGroup, ExpandableNotificationRow parent) {;
325 boolean childInGroup = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup;
326 mNotificationParent = childInGroup ? parent : null;
327 mPrivateLayout.setIsChildInGroup(childInGroup);
328 updateNoBackgroundState();
Selim Cinek34d93b02015-10-22 12:30:38 -0700329 }
330
331 @Override
Selim Cinek72109472016-01-15 16:33:22 -0800332 public boolean onTouchEvent(MotionEvent event) {
333 if (event.getActionMasked() != MotionEvent.ACTION_DOWN
334 || !isChildInGroup() || isGroupExpanded()) {
335 return super.onTouchEvent(event);
336 } else {
337 return false;
338 }
339 }
340
341 @Override
Mady Mellorf0625802016-02-11 18:03:48 -0800342 protected boolean handleSlideBack() {
343 if (mSettingsIconRow != null && mSettingsIconRow.isVisible()) {
344 animateTranslateNotification(0 /* targetLeft */);
345 return true;
346 }
347 return false;
348 }
349
350 @Override
Selim Cinek34d93b02015-10-22 12:30:38 -0700351 protected boolean shouldHideBackground() {
352 return super.shouldHideBackground() || mShowNoBackground;
Selim Cinek263398f2015-10-21 17:40:23 -0700353 }
354
355 @Override
356 public boolean isSummaryWithChildren() {
357 return mIsSummaryWithChildren;
Selim Cinekb5605e52015-02-20 18:21:41 +0100358 }
359
360 @Override
361 public boolean areChildrenExpanded() {
362 return mChildrenExpanded;
363 }
364
365 public List<ExpandableNotificationRow> getNotificationChildren() {
366 return mChildrenContainer == null ? null : mChildrenContainer.getNotificationChildren();
367 }
368
Selim Cinekeef84282015-10-30 16:28:00 -0700369 public int getNumberOfNotificationChildren() {
370 if (mChildrenContainer == null) {
371 return 0;
372 }
373 return mChildrenContainer.getNotificationChildren().size();
374 }
375
Selim Cinekb5605e52015-02-20 18:21:41 +0100376 /**
377 * Apply the order given in the list to the children.
378 *
379 * @param childOrder the new list order
380 * @return whether the list order has changed
381 */
382 public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder) {
383 return mChildrenContainer != null && mChildrenContainer.applyChildOrder(childOrder);
384 }
385
386 public void getChildrenStates(StackScrollState resultState) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700387 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100388 StackViewState parentState = resultState.getViewStateForView(this);
389 mChildrenContainer.getState(resultState, parentState);
390 }
391 }
392
393 public void applyChildrenState(StackScrollState state) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700394 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100395 mChildrenContainer.applyState(state);
396 }
397 }
398
399 public void prepareExpansionChanged(StackScrollState state) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700400 if (mIsSummaryWithChildren) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100401 mChildrenContainer.prepareExpansionChanged(state);
402 }
403 }
404
405 public void startChildAnimation(StackScrollState finalState,
Selim Cinek99695592016-01-12 17:51:35 -0800406 StackStateAnimator stateAnimator, long delay, long duration) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700407 if (mIsSummaryWithChildren) {
Selim Cinek99695592016-01-12 17:51:35 -0800408 mChildrenContainer.startAnimationToState(finalState, stateAnimator, delay,
Selim Cinekb5605e52015-02-20 18:21:41 +0100409 duration);
410 }
411 }
412
413 public ExpandableNotificationRow getViewAtPosition(float y) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700414 if (!mIsSummaryWithChildren || !mChildrenExpanded) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100415 return this;
416 } else {
417 ExpandableNotificationRow view = mChildrenContainer.getViewAtPosition(y);
418 return view == null ? this : view;
419 }
420 }
421
Selim Cinekab29aeb2015-02-20 18:18:32 +0100422 public NotificationGuts getGuts() {
423 return mGuts;
424 }
425
Selim Cinek684a4422015-04-15 16:18:39 -0700426 /**
427 * Set this notification to be pinned to the top if {@link #isHeadsUp()} is true. By doing this
428 * the notification will be rendered on top of the screen.
429 *
430 * @param pinned whether it is pinned
431 */
432 public void setPinned(boolean pinned) {
433 mIsPinned = pinned;
Selim Cinek31aada42015-12-18 17:51:15 -0800434 if (pinned) {
435 setIconAnimationRunning(true);
436 mExpandedWhenPinned = false;
437 } else if (mExpandedWhenPinned) {
438 setUserExpanded(true);
439 }
Selim Cinek98713a42015-09-21 15:47:20 +0200440 setChronometerRunning(mLastChronometerRunning);
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700441 }
442
Selim Cinek684a4422015-04-15 16:18:39 -0700443 public boolean isPinned() {
444 return mIsPinned;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700445 }
446
Selim Cinek31aada42015-12-18 17:51:15 -0800447 /**
448 * @param atLeastMinHeight should the value returned be at least the minimum height.
449 * Used to avoid cyclic calls
450 * @return the height of the heads up notification when pinned
451 */
452 public int getPinnedHeadsUpHeight(boolean atLeastMinHeight) {
Selim Cinek77019c72015-12-09 10:18:02 -0800453 if (mIsSummaryWithChildren) {
454 return mChildrenContainer.getIntrinsicHeight();
455 }
Selim Cinek31aada42015-12-18 17:51:15 -0800456 if(mExpandedWhenPinned) {
457 return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
458 } else if (atLeastMinHeight) {
459 return Math.max(getMinHeight(), mHeadsUpHeight);
460 } else {
461 return mHeadsUpHeight;
462 }
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700463 }
464
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700465 /**
466 * Mark whether this notification was just clicked, i.e. the user has just clicked this
467 * notification in this frame.
468 */
469 public void setJustClicked(boolean justClicked) {
470 mJustClicked = justClicked;
471 }
472
473 /**
474 * @return true if this notification has been clicked in this frame, false otherwise
475 */
476 public boolean wasJustClicked() {
477 return mJustClicked;
478 }
479
Selim Cinek98713a42015-09-21 15:47:20 +0200480 public void setChronometerRunning(boolean running) {
481 mLastChronometerRunning = running;
482 setChronometerRunning(running, mPrivateLayout);
483 setChronometerRunning(running, mPublicLayout);
484 if (mChildrenContainer != null) {
485 List<ExpandableNotificationRow> notificationChildren =
486 mChildrenContainer.getNotificationChildren();
487 for (int i = 0; i < notificationChildren.size(); i++) {
488 ExpandableNotificationRow child = notificationChildren.get(i);
489 child.setChronometerRunning(running);
490 }
491 }
492 }
493
494 private void setChronometerRunning(boolean running, NotificationContentView layout) {
495 if (layout != null) {
496 running = running || isPinned();
497 View contractedChild = layout.getContractedChild();
498 View expandedChild = layout.getExpandedChild();
499 View headsUpChild = layout.getHeadsUpChild();
500 setChronometerRunningForChild(running, contractedChild);
501 setChronometerRunningForChild(running, expandedChild);
502 setChronometerRunningForChild(running, headsUpChild);
503 }
504 }
505
506 private void setChronometerRunningForChild(boolean running, View child) {
507 if (child != null) {
508 View chronometer = child.findViewById(com.android.internal.R.id.chronometer);
509 if (chronometer instanceof Chronometer) {
510 ((Chronometer) chronometer).setStarted(running);
511 }
512 }
513 }
514
Selim Cinekea4bef72015-12-02 15:51:10 -0800515 public NotificationHeaderView getNotificationHeader() {
516 if (mNotificationHeader != null) {
517 return mNotificationHeader;
Selim Cinek8d6440d2015-10-22 13:00:05 -0700518 }
Selim Cinekea4bef72015-12-02 15:51:10 -0800519 return mPrivateLayout.getNotificationHeader();
Selim Cinek8d6440d2015-10-22 13:00:05 -0700520 }
521
Selim Cinek34eda5e2016-02-18 17:10:43 -0800522 private NotificationHeaderView getVisibleNotificationHeader() {
523 if (mNotificationHeader != null) {
524 return mNotificationHeader;
525 }
526 return getShowingLayout().getVisibleNotificationHeader();
527 }
528
Selim Cinek570981d2015-12-01 11:37:01 -0800529 public void setOnExpandClickListener(OnExpandClickListener onExpandClickListener) {
530 mOnExpandClickListener = onExpandClickListener;
531 }
532
Selim Cinek31aada42015-12-18 17:51:15 -0800533 public void setHeadsUpManager(HeadsUpManager headsUpManager) {
534 mHeadsUpManager = headsUpManager;
535 }
536
Selim Cinek01af3342016-02-09 19:25:31 -0800537 public void reInflateViews() {
538 initDimens();
539 if (mIsSummaryWithChildren) {
540 removeView(mNotificationHeader);
541 mNotificationHeader = null;
542 recreateNotificationHeader();
543 if (mChildrenContainer != null) {
544 mChildrenContainer.reInflateViews();
545 }
546 }
547 if (mGuts != null) {
548 View oldGuts = mGuts;
549 int index = indexOfChild(oldGuts);
550 removeView(oldGuts);
551 mGuts = (NotificationGuts) LayoutInflater.from(mContext).inflate(
552 R.layout.notification_guts, this, false);
553 mGuts.setVisibility(oldGuts.getVisibility());
554 addView(mGuts, index);
555 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800556 if (mSettingsIconRow != null) {
557 View oldSettings = mSettingsIconRow;
558 int settingsIndex = indexOfChild(oldSettings);
559 removeView(oldSettings);
560 mSettingsIconRow = (NotificationSettingsIconRow) LayoutInflater.from(mContext).inflate(
561 R.layout.notification_settings_icon_row, this, false);
562 mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this);
563 mSettingsIconRow.setVisibility(oldSettings.getVisibility());
564 addView(mSettingsIconRow, settingsIndex);
565
566 }
Selim Cinekde33a4a2016-02-11 16:43:41 -0800567 mPrivateLayout.reInflateViews();
568 mPublicLayout.reInflateViews();
Selim Cinek01af3342016-02-09 19:25:31 -0800569 }
570
Chris Wren78403d72014-07-28 10:23:24 +0100571 public interface ExpansionLogger {
572 public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
573 }
Selim Cinek1685e632014-04-08 02:27:49 +0200574
Chris Wren51c75102013-07-16 20:49:17 -0400575 public ExpandableNotificationRow(Context context, AttributeSet attrs) {
576 super(context, attrs);
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700577 mFalsingManager = FalsingManager.getInstance(context);
Selim Cinek01af3342016-02-09 19:25:31 -0800578 initDimens();
579 }
580
581 private void initDimens() {
Selim Cinekf619ffc2016-02-17 14:53:05 -0800582 mNotificationMinHeightLegacy = getFontScaledHeight(R.dimen.notification_min_height_legacy);
583 mNotificationMinHeight = getFontScaledHeight(R.dimen.notification_min_height);
584 mNotificationMaxHeight = getFontScaledHeight(R.dimen.notification_max_height);
585 mMaxHeadsUpHeightLegacy = getFontScaledHeight(
Selim Cinek77019c72015-12-09 10:18:02 -0800586 R.dimen.notification_max_heads_up_height_legacy);
Selim Cinekf619ffc2016-02-17 14:53:05 -0800587 mMaxHeadsUpHeight = getFontScaledHeight(R.dimen.notification_max_heads_up_height);
588 }
589
590 /**
591 * @param dimenId the dimen to look up
592 * @return the font scaled dimen as if it were in sp but doesn't shrink sizes below dp
593 */
594 private int getFontScaledHeight(int dimenId) {
595 int dimensionPixelSize = getResources().getDimensionPixelSize(dimenId);
596 float factor = Math.max(1.0f, getResources().getDisplayMetrics().scaledDensity /
597 getResources().getDisplayMetrics().density);
598 return (int) (dimensionPixelSize * factor);
Chris Wren51c75102013-07-16 20:49:17 -0400599 }
600
Christoph Studera7fe6312014-06-27 19:32:44 +0200601 /**
602 * Resets this view so it can be re-used for an updated notification.
603 */
Christoph Studer22f2ee52014-07-29 22:57:21 +0200604 @Override
Christoph Studera7fe6312014-06-27 19:32:44 +0200605 public void reset() {
Christoph Studer22f2ee52014-07-29 22:57:21 +0200606 super.reset();
Chris Wren78403d72014-07-28 10:23:24 +0100607 final boolean wasExpanded = isExpanded();
Christoph Studera7fe6312014-06-27 19:32:44 +0200608 mExpandable = false;
609 mHasUserChangedExpansion = false;
610 mUserLocked = false;
611 mShowingPublic = false;
Jorim Jaggiae441282014-08-01 02:45:18 +0200612 mSensitive = false;
613 mShowingPublicInitialized = false;
Christoph Studera7fe6312014-06-27 19:32:44 +0200614 mIsSystemExpanded = false;
Selim Cinek83bc7832015-10-22 13:26:54 -0700615 mOnKeyguard = false;
Selim Cinek1a521f32014-11-03 17:39:29 +0100616 mPublicLayout.reset(mIsHeadsUp);
617 mPrivateLayout.reset(mIsHeadsUp);
Selim Cinek31094df2014-08-14 19:28:15 +0200618 resetHeight();
Mady Mellor4b80b102016-01-22 08:03:58 -0800619 resetTranslation();
Selim Cinek31094df2014-08-14 19:28:15 +0200620 logExpansionEvent(false, wasExpanded);
621 }
622
623 public void resetHeight() {
Selim Cinek1a521f32014-11-03 17:39:29 +0100624 if (mIsHeadsUp) {
625 resetActualHeight();
626 }
Christoph Studera7fe6312014-06-27 19:32:44 +0200627 mMaxExpandHeight = 0;
Selim Cinek8d490d42015-04-10 00:05:50 -0700628 mHeadsUpHeight = 0;
Selim Cineka5e211b2014-08-11 17:35:48 +0200629 mWasReset = true;
Selim Cinek31094df2014-08-14 19:28:15 +0200630 onHeightReset();
Selim Cinek6e28a672014-09-05 14:43:28 +0200631 requestLayout();
Christoph Studera7fe6312014-06-27 19:32:44 +0200632 }
633
Jorim Jaggi251957d2014-04-09 04:24:09 +0200634 @Override
635 protected void onFinishInflate() {
636 super.onFinishInflate();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200637 mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
Selim Cinekfa0a2d32016-01-14 13:02:21 -0800638 mPublicLayout.setContainingNotification(this);
Jorim Jaggibe565df2014-04-28 17:51:23 +0200639 mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800640 mPrivateLayout.setExpandClickListener(mExpandClickListener);
Selim Cinekfa0a2d32016-01-14 13:02:21 -0800641 mPrivateLayout.setContainingNotification(this);
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800642 mPublicLayout.setExpandClickListener(mExpandClickListener);
Mady Mellor4b80b102016-01-22 08:03:58 -0800643 mSettingsIconRowStub = (ViewStub) findViewById(R.id.settings_icon_row_stub);
644 mSettingsIconRowStub.setOnInflateListener(new ViewStub.OnInflateListener() {
645 @Override
646 public void onInflate(ViewStub stub, View inflated) {
647 mSettingsIconRow = (NotificationSettingsIconRow) inflated;
648 mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this);
649 }
650 });
Selim Cinekab29aeb2015-02-20 18:18:32 +0100651 mGutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
652 mGutsStub.setOnInflateListener(new ViewStub.OnInflateListener() {
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200653 @Override
654 public void onInflate(ViewStub stub, View inflated) {
655 mGuts = (NotificationGuts) inflated;
656 mGuts.setClipTopAmount(getClipTopAmount());
657 mGuts.setActualHeight(getActualHeight());
Mady Mellor4b80b102016-01-22 08:03:58 -0800658 mTranslateableViews.add(mGuts);
Selim Cinekab29aeb2015-02-20 18:18:32 +0100659 mGutsStub = null;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200660 }
661 });
Selim Cinekb5605e52015-02-20 18:21:41 +0100662 mChildrenContainerStub = (ViewStub) findViewById(R.id.child_container_stub);
663 mChildrenContainerStub.setOnInflateListener(new ViewStub.OnInflateListener() {
664
665 @Override
666 public void onInflate(ViewStub stub, View inflated) {
667 mChildrenContainer = (NotificationChildrenContainer) inflated;
Selim Cinek388df6d2015-10-22 13:25:11 -0700668 mChildrenContainer.setNotificationParent(ExpandableNotificationRow.this);
Mady Mellor4b80b102016-01-22 08:03:58 -0800669 mTranslateableViews.add(mChildrenContainer);
Selim Cinekb5605e52015-02-20 18:21:41 +0100670 }
671 });
Selim Cinek863834b2014-05-20 04:20:25 +0200672 mVetoButton = findViewById(R.id.veto);
Mady Mellor4b80b102016-01-22 08:03:58 -0800673
674 // Add the views that we translate to reveal the gear
675 mTranslateableViews = new ArrayList<View>();
676 for (int i = 0; i < getChildCount(); i++) {
677 mTranslateableViews.add(getChildAt(i));
678 }
679 // Remove views that don't translate
680 mTranslateableViews.remove(mVetoButton);
681 mTranslateableViews.remove(mSettingsIconRowStub);
682 mTranslateableViews.remove(mChildrenContainerStub);
683 mTranslateableViews.remove(mGutsStub);
684 }
685
686 public void setTranslationForOutline(float translationX) {
687 setOutlineRect(false, translationX, getTop(), getRight() + translationX, getBottom());
688 }
689
690 public void resetTranslation() {
691 if (mTranslateableViews != null) {
692 for (int i = 0; i < mTranslateableViews.size(); i++) {
693 mTranslateableViews.get(i).setTranslationX(0);
694 }
695 setTranslationForOutline(0);
696 }
697 if (mSettingsIconRow != null) {
698 mSettingsIconRow.resetState();
699 }
700 }
701
702 public void animateTranslateNotification(final float leftTarget) {
703 if (mTranslateAnim != null) {
704 mTranslateAnim.cancel();
705 }
706 AnimatorSet set = new AnimatorSet();
707 if (mTranslateableViews != null) {
708 for (int i = 0; i < mTranslateableViews.size(); i++) {
709 final View animView = mTranslateableViews.get(i);
710 final ObjectAnimator translateAnim = ObjectAnimator.ofFloat(
711 animView, "translationX", leftTarget);
712 if (i == 0) {
713 translateAnim.addUpdateListener(new AnimatorUpdateListener() {
714 @Override
715 public void onAnimationUpdate(ValueAnimator animation) {
716 setTranslationForOutline((float) animation.getAnimatedValue());
717 }
718 });
719 }
720 translateAnim.addListener(new AnimatorListenerAdapter() {
721 @Override
722 public void onAnimationEnd(Animator anim) {
723 if (mSettingsIconRow != null && leftTarget == 0) {
724 mSettingsIconRow.resetState();
725 }
726 mTranslateAnim = null;
727 }
728 });
729 set.play(translateAnim);
730 }
731 }
732 mTranslateAnim = set;
733 set.start();
734 }
735
736 public float getSpaceForGear() {
737 if (mSettingsIconRow != null) {
738 return mSettingsIconRow.getSpaceForGear();
739 }
740 return 0;
741 }
742
743 public NotificationSettingsIconRow getSettingsRow() {
744 if (mSettingsIconRow == null) {
745 mSettingsIconRowStub.inflate();
746 }
747 return mSettingsIconRow;
748 }
749
750 public ArrayList<View> getContentViews() {
751 return mTranslateableViews;
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200752 }
753
Selim Cinekab29aeb2015-02-20 18:18:32 +0100754 public void inflateGuts() {
755 if (mGuts == null) {
756 mGutsStub.inflate();
757 }
758 }
759
Selim Cinekda42d652015-12-04 15:51:16 -0800760 private void updateChildrenVisibility() {
Selim Cinekd84a5932015-12-15 11:45:36 -0800761 mPrivateLayout.setVisibility(!mShowingPublic && !mIsSummaryWithChildren ? VISIBLE
762 : INVISIBLE);
Selim Cinekef5127e2015-12-21 16:55:58 -0800763 if (mChildrenContainer != null) {
764 mChildrenContainer.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
765 : INVISIBLE);
Selim Cinekb5605e52015-02-20 18:21:41 +0100766 }
Selim Cinekef5127e2015-12-21 16:55:58 -0800767 if (mNotificationHeader != null) {
768 mNotificationHeader.setVisibility(!mShowingPublic && mIsSummaryWithChildren ? VISIBLE
769 : INVISIBLE);
770 }
Selim Cinekda42d652015-12-04 15:51:16 -0800771 // The limits might have changed if the view suddenly became a group or vice versa
772 updateLimits();
Selim Cinekb5605e52015-02-20 18:21:41 +0100773 }
774
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200775 @Override
Alan Viverettea54956a2015-01-07 16:05:02 -0800776 public boolean onRequestSendAccessibilityEventInternal(View child, AccessibilityEvent event) {
777 if (super.onRequestSendAccessibilityEventInternal(child, event)) {
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200778 // Add a record for the entire layout since its content is somehow small.
779 // The event comes from a leaf view that is interacted with.
780 AccessibilityEvent record = AccessibilityEvent.obtain();
781 onInitializeAccessibilityEvent(record);
782 dispatchPopulateAccessibilityEvent(record);
783 event.appendRecord(record);
784 return true;
785 }
786 return false;
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200787 }
Chris Wren51c75102013-07-16 20:49:17 -0400788
John Spurlocke15452b2014-08-21 09:44:39 -0400789 @Override
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100790 public void setDark(boolean dark, boolean fade, long delay) {
791 super.setDark(dark, fade, delay);
John Spurlocke15452b2014-08-21 09:44:39 -0400792 final NotificationContentView showing = getShowingLayout();
793 if (showing != null) {
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100794 showing.setDark(dark, fade, delay);
John Spurlocke15452b2014-08-21 09:44:39 -0400795 }
Selim Cinek9c7712d2015-12-08 19:19:48 -0800796 if (mIsSummaryWithChildren) {
797 mChildrenContainer.setDark(dark, fade, delay);
798 mNotificationHeaderWrapper.setDark(dark, fade, delay);
799 }
John Spurlocke15452b2014-08-21 09:44:39 -0400800 }
801
Chris Wren51c75102013-07-16 20:49:17 -0400802 public boolean isExpandable() {
Selim Cinek388df6d2015-10-22 13:25:11 -0700803 if (mIsSummaryWithChildren && !mShowingPublic) {
804 return !mChildrenExpanded;
805 }
Chris Wren51c75102013-07-16 20:49:17 -0400806 return mExpandable;
807 }
808
809 public void setExpandable(boolean expandable) {
810 mExpandable = expandable;
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800811 mPrivateLayout.updateExpandButtons(isExpandable());
Chris Wren51c75102013-07-16 20:49:17 -0400812 }
813
Selim Cinek4ffd6362015-12-29 15:12:23 +0100814 @Override
815 public void setClipToActualHeight(boolean clipToActualHeight) {
Selim Cinek084c16b2016-01-22 17:48:22 -0800816 super.setClipToActualHeight(clipToActualHeight || isUserLocked());
817 getShowingLayout().setClipToActualHeight(clipToActualHeight || isUserLocked());
Selim Cinek4ffd6362015-12-29 15:12:23 +0100818 }
819
Selim Cinek1685e632014-04-08 02:27:49 +0200820 /**
821 * @return whether the user has changed the expansion state
822 */
823 public boolean hasUserChangedExpansion() {
824 return mHasUserChangedExpansion;
825 }
826
Chris Wren51c75102013-07-16 20:49:17 -0400827 public boolean isUserExpanded() {
828 return mUserExpanded;
829 }
830
Selim Cinek1685e632014-04-08 02:27:49 +0200831 /**
832 * Set this notification to be expanded by the user
833 *
834 * @param userExpanded whether the user wants this notification to be expanded
835 */
Chris Wren51c75102013-07-16 20:49:17 -0400836 public void setUserExpanded(boolean userExpanded) {
Selim Cinek388df6d2015-10-22 13:25:11 -0700837 setUserExpanded(userExpanded, false /* allowChildExpansion */);
838 }
839
840 /**
841 * Set this notification to be expanded by the user
842 *
843 * @param userExpanded whether the user wants this notification to be expanded
844 * @param allowChildExpansion whether a call to this method allows expanding children
845 */
846 public void setUserExpanded(boolean userExpanded, boolean allowChildExpansion) {
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700847 mFalsingManager.setNotificationExpanded();
Selim Cinek388df6d2015-10-22 13:25:11 -0700848 if (mIsSummaryWithChildren && !mShowingPublic && allowChildExpansion) {
849 mGroupManager.setGroupExpanded(mStatusBarNotification, userExpanded);
850 return;
851 }
Christoph Studera7fe6312014-06-27 19:32:44 +0200852 if (userExpanded && !mExpandable) return;
Chris Wren78403d72014-07-28 10:23:24 +0100853 final boolean wasExpanded = isExpanded();
Selim Cinek1685e632014-04-08 02:27:49 +0200854 mHasUserChangedExpansion = true;
Chris Wren51c75102013-07-16 20:49:17 -0400855 mUserExpanded = userExpanded;
Chris Wren78403d72014-07-28 10:23:24 +0100856 logExpansionEvent(true, wasExpanded);
Chris Wren51c75102013-07-16 20:49:17 -0400857 }
858
Selim Cinekccd14fb2014-08-12 18:53:24 +0200859 public void resetUserExpansion() {
860 mHasUserChangedExpansion = false;
861 mUserExpanded = false;
862 }
863
Chris Wren51c75102013-07-16 20:49:17 -0400864 public boolean isUserLocked() {
865 return mUserLocked;
866 }
867
868 public void setUserLocked(boolean userLocked) {
869 mUserLocked = userLocked;
870 }
871
Selim Cinek1685e632014-04-08 02:27:49 +0200872 /**
873 * @return has the system set this notification to be expanded
874 */
875 public boolean isSystemExpanded() {
876 return mIsSystemExpanded;
877 }
878
879 /**
880 * Set this notification to be expanded by the system.
881 *
882 * @param expand whether the system wants this notification to be expanded.
883 */
884 public void setSystemExpanded(boolean expand) {
Selim Cinek31094df2014-08-14 19:28:15 +0200885 if (expand != mIsSystemExpanded) {
886 final boolean wasExpanded = isExpanded();
887 mIsSystemExpanded = expand;
Selim Cinekb5605e52015-02-20 18:21:41 +0100888 notifyHeightChanged(false /* needsAnimation */);
Selim Cinek31094df2014-08-14 19:28:15 +0200889 logExpansionEvent(false, wasExpanded);
Selim Cinek83bc7832015-10-22 13:26:54 -0700890 if (mChildrenContainer != null) {
891 mChildrenContainer.updateGroupOverflow();
892 }
Selim Cinek31094df2014-08-14 19:28:15 +0200893 }
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200894 }
895
896 /**
Selim Cinek83bc7832015-10-22 13:26:54 -0700897 * @param onKeyguard whether to prevent notification expansion
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200898 */
Selim Cinek83bc7832015-10-22 13:26:54 -0700899 public void setOnKeyguard(boolean onKeyguard) {
900 if (onKeyguard != mOnKeyguard) {
Selim Cinek31094df2014-08-14 19:28:15 +0200901 final boolean wasExpanded = isExpanded();
Selim Cinek83bc7832015-10-22 13:26:54 -0700902 mOnKeyguard = onKeyguard;
Selim Cinek31094df2014-08-14 19:28:15 +0200903 logExpansionEvent(false, wasExpanded);
904 if (wasExpanded != isExpanded()) {
Selim Cinek2108fe02015-12-10 12:56:13 -0800905 if (mIsSummaryWithChildren) {
906 mChildrenContainer.updateGroupOverflow();
907 }
Mady Mellor4b80b102016-01-22 08:03:58 -0800908 notifyHeightChanged(false /* needsAnimation */);
Selim Cinek31094df2014-08-14 19:28:15 +0200909 }
910 }
Selim Cinek1685e632014-04-08 02:27:49 +0200911 }
912
913 /**
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400914 * @return Can the underlying notification be cleared?
915 */
916 public boolean isClearable() {
Selim Cineka37774f2014-11-11 19:16:18 +0100917 return mStatusBarNotification != null && mStatusBarNotification.isClearable();
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400918 }
919
920 /**
Selim Cinek1685e632014-04-08 02:27:49 +0200921 * Apply an expansion state to the layout.
Selim Cinek1685e632014-04-08 02:27:49 +0200922 */
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200923 public void applyExpansionToLayout() {
924 boolean expand = isExpanded();
Chris Wren51c75102013-07-16 20:49:17 -0400925 if (expand && mExpandable) {
Selim Cinekeef84282015-10-30 16:28:00 -0700926 setActualHeight(mMaxExpandHeight);
Chris Wren51c75102013-07-16 20:49:17 -0400927 } else {
Selim Cinek860b6da2015-12-16 19:02:19 -0800928 setActualHeight(getMinHeight());
Chris Wren51c75102013-07-16 20:49:17 -0400929 }
Chris Wren51c75102013-07-16 20:49:17 -0400930 }
Dan Sandlera5e0f412014-01-23 15:11:54 -0500931
Jorim Jaggi9cbadd32014-05-01 20:18:31 +0200932 @Override
933 public int getIntrinsicHeight() {
Jorim Jaggibe565df2014-04-28 17:51:23 +0200934 if (isUserLocked()) {
935 return getActualHeight();
936 }
Selim Cinekd84a5932015-12-15 11:45:36 -0800937 if (mGuts != null && mGuts.areGutsExposed()) {
938 return mGuts.getHeight();
939 } else if ((isChildInGroup() && !isGroupExpanded())) {
940 return mPrivateLayout.getMinHeight();
941 } else if (mSensitive && mHideSensitiveForIntrinsicHeight) {
942 return getMinHeight();
Selim Cinek83bc7832015-10-22 13:26:54 -0700943 } else if (mIsSummaryWithChildren && !mOnKeyguard) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800944 return mChildrenContainer.getIntrinsicHeight();
Selim Cinek60122be2015-04-15 18:16:50 -0700945 } else if (mIsHeadsUp) {
Selim Cinek31aada42015-12-18 17:51:15 -0800946 if (isPinned()) {
947 return getPinnedHeadsUpHeight(true /* atLeastMinHeight */);
948 } else if (isExpanded()) {
Selim Cinekd84a5932015-12-15 11:45:36 -0800949 return Math.max(getMaxExpandHeight(), mHeadsUpHeight);
Selim Cinek8d490d42015-04-10 00:05:50 -0700950 } else {
Selim Cinekd84a5932015-12-15 11:45:36 -0800951 return Math.max(getMinHeight(), mHeadsUpHeight);
Selim Cinek8d490d42015-04-10 00:05:50 -0700952 }
Selim Cinek31aada42015-12-18 17:51:15 -0800953 } else if (isExpanded()) {
Selim Cinek83bc7832015-10-22 13:26:54 -0700954 return getMaxExpandHeight();
Selim Cinekd84a5932015-12-15 11:45:36 -0800955 } else {
956 return getMinHeight();
Selim Cinek1685e632014-04-08 02:27:49 +0200957 }
Selim Cinekb5605e52015-02-20 18:21:41 +0100958 }
Selim Cinek1685e632014-04-08 02:27:49 +0200959
Selim Cinekeef84282015-10-30 16:28:00 -0700960 private boolean isGroupExpanded() {
961 return mGroupManager.isGroupExpanded(mStatusBarNotification);
Selim Cinekb5605e52015-02-20 18:21:41 +0100962 }
963
Selim Cinekeef84282015-10-30 16:28:00 -0700964 /**
965 * @return whether this view has a header on the top of the content
966 */
967 private boolean hasNotificationHeader() {
968 return mIsSummaryWithChildren;
Selim Cinek1685e632014-04-08 02:27:49 +0200969 }
970
Selim Cinek263398f2015-10-21 17:40:23 -0700971 private void onChildrenCountChanged() {
Selim Cinek8fc93c92015-11-23 17:48:07 -0800972 mIsSummaryWithChildren = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS
Selim Cinek263398f2015-10-21 17:40:23 -0700973 && mGroupManager.hasGroupChildren(mStatusBarNotification);
Selim Cinek8fc93c92015-11-23 17:48:07 -0800974 if (mIsSummaryWithChildren) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800975 if (mChildrenContainer == null) {
976 mChildrenContainerStub.inflate();
977 }
Selim Cinek8fc93c92015-11-23 17:48:07 -0800978 if (mNotificationHeader == null) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800979 recreateNotificationHeader();
980 }
Selim Cinek263398f2015-10-21 17:40:23 -0700981 }
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800982 mPrivateLayout.updateExpandButtons(isExpandable());
Selim Cinekea4bef72015-12-02 15:51:10 -0800983 updateChildrenHeaderAppearance();
Selim Cinekeaa29ca2015-11-23 13:51:13 -0800984 updateHeaderChildCount();
Selim Cinekda42d652015-12-04 15:51:16 -0800985 updateChildrenVisibility();
Selim Cinek263398f2015-10-21 17:40:23 -0700986 }
987
Selim Cinek1685e632014-04-08 02:27:49 +0200988 /**
989 * Check whether the view state is currently expanded. This is given by the system in {@link
990 * #setSystemExpanded(boolean)} and can be overridden by user expansion or
991 * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this
992 * view can differ from this state, if layout params are modified from outside.
993 *
994 * @return whether the view state is currently expanded.
995 */
Selim Cinek83bc7832015-10-22 13:26:54 -0700996 public boolean isExpanded() {
997 return !mOnKeyguard
Selim Cinekb5605e52015-02-20 18:21:41 +0100998 && (!hasUserChangedExpansion() && (isSystemExpanded() || isSystemChildExpanded())
999 || isUserExpanded());
1000 }
1001
1002 private boolean isSystemChildExpanded() {
1003 return mIsSystemChildExpanded;
1004 }
1005
1006 public void setSystemChildExpanded(boolean expanded) {
1007 mIsSystemChildExpanded = expanded;
Selim Cinek1685e632014-04-08 02:27:49 +02001008 }
1009
1010 @Override
1011 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
1012 super.onLayout(changed, left, top, right, bottom);
Selim Cineka5e211b2014-08-11 17:35:48 +02001013 boolean updateExpandHeight = mMaxExpandHeight == 0 && !mWasReset;
Selim Cinek8d490d42015-04-10 00:05:50 -07001014 updateMaxHeights();
Jorim Jaggibe565df2014-04-28 17:51:23 +02001015 if (updateExpandHeight) {
Jorim Jaggidce3c4c2014-04-29 23:12:24 +02001016 applyExpansionToLayout();
Jorim Jaggibe565df2014-04-28 17:51:23 +02001017 }
Selim Cineka5e211b2014-08-11 17:35:48 +02001018 mWasReset = false;
Selim Cinek1685e632014-04-08 02:27:49 +02001019 }
1020
Selim Cinek8d490d42015-04-10 00:05:50 -07001021 private void updateMaxHeights() {
Selim Cinekd2319fb2014-09-01 19:41:54 +02001022 int intrinsicBefore = getIntrinsicHeight();
Selim Cinek8d490d42015-04-10 00:05:50 -07001023 View expandedChild = mPrivateLayout.getExpandedChild();
1024 if (expandedChild == null) {
1025 expandedChild = mPrivateLayout.getContractedChild();
1026 }
1027 mMaxExpandHeight = expandedChild.getHeight();
1028 View headsUpChild = mPrivateLayout.getHeadsUpChild();
Selim Cinek1f3f5442015-04-10 17:54:46 -07001029 if (headsUpChild == null) {
1030 headsUpChild = mPrivateLayout.getContractedChild();
Selim Cinek8d490d42015-04-10 00:05:50 -07001031 }
Selim Cinek1f3f5442015-04-10 17:54:46 -07001032 mHeadsUpHeight = headsUpChild.getHeight();
Selim Cinekd2319fb2014-09-01 19:41:54 +02001033 if (intrinsicBefore != getIntrinsicHeight()) {
Selim Cinekb5605e52015-02-20 18:21:41 +01001034 notifyHeightChanged(false /* needsAnimation */);
Selim Cinekd2319fb2014-09-01 19:41:54 +02001035 }
1036 }
1037
Selim Cinekfa0a2d32016-01-14 13:02:21 -08001038 @Override
1039 public void notifyHeightChanged(boolean needsAnimation) {
1040 super.notifyHeightChanged(needsAnimation);
1041 getShowingLayout().requestSelectLayout(needsAnimation || isUserLocked());
1042 }
1043
Jorim Jaggiae441282014-08-01 02:45:18 +02001044 public void setSensitive(boolean sensitive) {
1045 mSensitive = sensitive;
1046 }
1047
1048 public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) {
Selim Cinek60122be2015-04-15 18:16:50 -07001049 mHideSensitiveForIntrinsicHeight = hideSensitive;
Jorim Jaggiae441282014-08-01 02:45:18 +02001050 }
1051
1052 public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
1053 long duration) {
1054 boolean oldShowingPublic = mShowingPublic;
1055 mShowingPublic = mSensitive && hideSensitive;
1056 if (mShowingPublicInitialized && mShowingPublic == oldShowingPublic) {
1057 return;
1058 }
Dan Sandlera5e0f412014-01-23 15:11:54 -05001059
1060 // bail out if no public version
Selim Cinek1685e632014-04-08 02:27:49 +02001061 if (mPublicLayout.getChildCount() == 0) return;
Dan Sandlera5e0f412014-01-23 15:11:54 -05001062
Jorim Jaggiae441282014-08-01 02:45:18 +02001063 if (!animated) {
1064 mPublicLayout.animate().cancel();
1065 mPrivateLayout.animate().cancel();
1066 mPublicLayout.setAlpha(1f);
1067 mPrivateLayout.setAlpha(1f);
1068 mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE);
Selim Cinekd84a5932015-12-15 11:45:36 -08001069 updateChildrenVisibility();
Jorim Jaggiae441282014-08-01 02:45:18 +02001070 } else {
1071 animateShowingPublic(delay, duration);
1072 }
Dan Sandler0d3e62f2014-07-14 17:13:50 -04001073
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001074 mPrivateLayout.updateExpandButtons(isExpandable());
Selim Cinek757d8792016-01-28 16:21:08 -08001075 updateClearability();
Jorim Jaggiae441282014-08-01 02:45:18 +02001076 mShowingPublicInitialized = true;
1077 }
1078
1079 private void animateShowingPublic(long delay, long duration) {
Selim Cinekd84a5932015-12-15 11:45:36 -08001080 View[] privateViews = mIsSummaryWithChildren ?
1081 new View[] {mChildrenContainer, mNotificationHeader}
1082 : new View[] {mPrivateLayout};
1083 View[] publicViews = new View[] {mPublicLayout};
1084 View[] hiddenChildren = mShowingPublic ? privateViews : publicViews;
1085 View[] shownChildren = mShowingPublic ? publicViews : privateViews;
1086 for (final View hiddenView : hiddenChildren) {
1087 hiddenView.setVisibility(View.VISIBLE);
1088 hiddenView.animate().cancel();
1089 hiddenView.animate()
1090 .alpha(0f)
1091 .setStartDelay(delay)
1092 .setDuration(duration)
1093 .withEndAction(new Runnable() {
1094 @Override
1095 public void run() {
1096 hiddenView.setVisibility(View.INVISIBLE);
1097 }
1098 });
1099 }
1100 for (View showView : shownChildren) {
1101 showView.setVisibility(View.VISIBLE);
1102 showView.setAlpha(0f);
1103 showView.animate().cancel();
1104 showView.animate()
1105 .alpha(1f)
1106 .setStartDelay(delay)
1107 .setDuration(duration);
1108 }
Dan Sandler0d3e62f2014-07-14 17:13:50 -04001109 }
1110
Selim Cinek3776fe02016-02-04 13:32:43 -08001111 public boolean mustStayOnScreen() {
1112 return mIsHeadsUp;
1113 }
1114
Selim Cinek757d8792016-01-28 16:21:08 -08001115 private void updateClearability() {
Dan Sandler0d3e62f2014-07-14 17:13:50 -04001116 // public versions cannot be dismissed
1117 mVetoButton.setVisibility(isClearable() && !mShowingPublic ? View.VISIBLE : View.GONE);
Dan Sandlera5e0f412014-01-23 15:11:54 -05001118 }
Jorim Jaggi251957d2014-04-09 04:24:09 +02001119
Selim Cinekb5605e52015-02-20 18:21:41 +01001120 public void setChildrenExpanded(boolean expanded, boolean animate) {
1121 mChildrenExpanded = expanded;
Selim Cinek7b836392015-12-04 20:02:59 -08001122 if (mNotificationHeader != null) {
1123 mNotificationHeader.setExpanded(expanded);
1124 }
Selim Cinek83bc7832015-10-22 13:26:54 -07001125 if (mChildrenContainer != null) {
1126 mChildrenContainer.setChildrenExpanded(expanded);
1127 }
Selim Cinekb5605e52015-02-20 18:21:41 +01001128 }
1129
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001130 public void updateHeaderChildCount() {
1131 if (mIsSummaryWithChildren) {
1132 mNotificationHeader.setChildCount(
1133 mChildrenContainer.getNotificationChildren().size());
Selim Cinekb5605e52015-02-20 18:21:41 +01001134 }
Selim Cinekb5605e52015-02-20 18:21:41 +01001135 }
1136
1137 public static void applyTint(View v, int color) {
1138 int alpha;
1139 if (color != 0) {
1140 alpha = COLORED_DIVIDER_ALPHA;
1141 } else {
1142 color = 0xff000000;
1143 alpha = DEFAULT_DIVIDER_ALPHA;
1144 }
1145 if (v.getBackground() instanceof ColorDrawable) {
1146 ColorDrawable background = (ColorDrawable) v.getBackground();
1147 background.mutate();
1148 background.setColor(color);
1149 background.setAlpha(alpha);
1150 }
1151 }
1152
Selim Cinek1685e632014-04-08 02:27:49 +02001153 public int getMaxExpandHeight() {
Selim Cinekb5605e52015-02-20 18:21:41 +01001154 return mMaxExpandHeight;
Chris Wren51c75102013-07-16 20:49:17 -04001155 }
Jorim Jaggi584a7aa2014-04-10 23:26:13 +02001156
Jorim Jaggibe565df2014-04-28 17:51:23 +02001157 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001158 public boolean isContentExpandable() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001159 NotificationContentView showingLayout = getShowingLayout();
1160 return showingLayout.isContentExpandable();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001161 }
1162
1163 @Override
Selim Cinek560e64d2015-06-09 19:58:11 -07001164 protected View getContentView() {
1165 return getShowingLayout();
1166 }
1167
1168 @Override
Jorim Jaggid552d9d2014-05-07 19:41:13 +02001169 public void setActualHeight(int height, boolean notifyListeners) {
Selim Cinekb5605e52015-02-20 18:21:41 +01001170 super.setActualHeight(height, notifyListeners);
Selim Cinekeef84282015-10-30 16:28:00 -07001171 int contentHeight = Math.max(getMinHeight(), height);
Selim Cinekb5605e52015-02-20 18:21:41 +01001172 mPrivateLayout.setContentHeight(contentHeight);
1173 mPublicLayout.setContentHeight(contentHeight);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001174 if (mGuts != null) {
1175 mGuts.setActualHeight(height);
1176 }
Jorim Jaggibe565df2014-04-28 17:51:23 +02001177 invalidate();
Jorim Jaggibe565df2014-04-28 17:51:23 +02001178 }
1179
1180 @Override
Selim Cinekb5605e52015-02-20 18:21:41 +01001181 public int getMaxContentHeight() {
Selim Cinek83bc7832015-10-22 13:26:54 -07001182 if (mIsSummaryWithChildren && !mShowingPublic) {
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001183 return mChildrenContainer.getMaxContentHeight();
Selim Cinek83bc7832015-10-22 13:26:54 -07001184 }
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001185 NotificationContentView showingLayout = getShowingLayout();
1186 return showingLayout.getMaxHeight();
Jorim Jaggibe565df2014-04-28 17:51:23 +02001187 }
1188
1189 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001190 public int getMinHeight() {
Selim Cinek31aada42015-12-18 17:51:15 -08001191 if (mIsHeadsUp && mHeadsUpManager.isTrackingHeadsUp()) {
1192 return getPinnedHeadsUpHeight(false /* atLeastMinHeight */);
1193 } else if (mIsSummaryWithChildren && !isGroupExpanded() && !mShowingPublic) {
Selim Cinekb55386d2015-12-16 17:26:49 -08001194 return mChildrenContainer.getMinHeight();
Selim Cinek31aada42015-12-18 17:51:15 -08001195 } else if (mIsHeadsUp) {
1196 return mHeadsUpHeight;
Selim Cinekb55386d2015-12-16 17:26:49 -08001197 }
Selim Cinek816c8e42015-11-19 12:00:45 -08001198 NotificationContentView showingLayout = getShowingLayout();
1199 return showingLayout.getMinHeight();
1200 }
1201
1202 @Override
1203 public int getMinExpandHeight() {
Selim Cinek83bc7832015-10-22 13:26:54 -07001204 if (mIsSummaryWithChildren && !mOnKeyguard) {
Selim Cinekb55386d2015-12-16 17:26:49 -08001205 return mChildrenContainer.getMinExpandHeight();
Selim Cinek83bc7832015-10-22 13:26:54 -07001206 }
Selim Cinek816c8e42015-11-19 12:00:45 -08001207 return getMinHeight();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02001208 }
1209
1210 @Override
Jorim Jaggibe565df2014-04-28 17:51:23 +02001211 public void setClipTopAmount(int clipTopAmount) {
1212 super.setClipTopAmount(clipTopAmount);
1213 mPrivateLayout.setClipTopAmount(clipTopAmount);
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001214 mPublicLayout.setClipTopAmount(clipTopAmount);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001215 if (mGuts != null) {
1216 mGuts.setClipTopAmount(clipTopAmount);
1217 }
Jorim Jaggibe565df2014-04-28 17:51:23 +02001218 }
1219
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001220 private void recreateNotificationHeader() {
1221 final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
1222 getStatusBarNotification().getNotification());
1223 final RemoteViews header = builder.makeNotificationHeader();
1224 if (mNotificationHeader == null) {
1225 mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this);
1226 final View expandButton = mNotificationHeader.findViewById(
1227 com.android.internal.R.id.expand_button);
1228 expandButton.setVisibility(VISIBLE);
1229 mNotificationHeader.setOnClickListener(mExpandClickListener);
Selim Cinek9c7712d2015-12-08 19:19:48 -08001230 mNotificationHeaderWrapper = NotificationViewWrapper.wrap(getContext(),
1231 mNotificationHeader);
Selim Cinekb5a83612015-12-11 14:14:39 -08001232 addView(mNotificationHeader, indexOfChild(mChildrenContainer) + 1);
Mady Mellor4b80b102016-01-22 08:03:58 -08001233 mTranslateableViews.add(mNotificationHeader);
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001234 } else {
1235 header.reapply(getContext(), mNotificationHeader);
Selim Cinek4ffd6362015-12-29 15:12:23 +01001236 mNotificationHeaderWrapper.notifyContentUpdated(mEntry.notification);
Selim Cinekeaa29ca2015-11-23 13:51:13 -08001237 }
Selim Cinek7b836392015-12-04 20:02:59 -08001238 updateHeaderExpandButton();
Selim Cinekea4bef72015-12-02 15:51:10 -08001239 updateChildrenHeaderAppearance();
Selim Cinek8fc93c92015-11-23 17:48:07 -08001240 updateHeaderChildCount();
Selim Cinek343e6e22014-04-11 21:23:30 +02001241 }
Selim Cinek7d447722014-06-10 15:51:59 +02001242
Selim Cinek7b836392015-12-04 20:02:59 -08001243 private void updateHeaderExpandButton() {
1244 if (mIsSummaryWithChildren) {
1245 mNotificationHeader.setIsGroupHeader(true /* isGroupHeader*/);
1246 }
1247 }
1248
Selim Cinekea4bef72015-12-02 15:51:10 -08001249 public void updateChildrenHeaderAppearance() {
1250 if (mIsSummaryWithChildren) {
1251 mHeaderUtil.updateChildrenHeaderAppearance();
1252 }
1253 }
1254
Selim Cinek31094df2014-08-14 19:28:15 +02001255 public boolean isMaxExpandHeightInitialized() {
1256 return mMaxExpandHeight != 0;
Selim Cinek7d447722014-06-10 15:51:59 +02001257 }
Selim Cinek2f0df8a2014-06-10 17:40:42 +02001258
1259 private NotificationContentView getShowingLayout() {
1260 return mShowingPublic ? mPublicLayout : mPrivateLayout;
1261 }
Chris Wren78403d72014-07-28 10:23:24 +01001262
Jorim Jaggi59ec3042015-06-05 15:18:43 -07001263 @Override
1264 public void setShowingLegacyBackground(boolean showing) {
1265 super.setShowingLegacyBackground(showing);
1266 mPrivateLayout.setShowingLegacyBackground(showing);
1267 mPublicLayout.setShowingLegacyBackground(showing);
1268 }
1269
Selim Cineka6c6bfb2015-10-29 16:27:08 -07001270 @Override
1271 protected void updateBackgroundTint() {
1272 super.updateBackgroundTint();
1273 updateNoBackgroundState();
1274 if (mIsSummaryWithChildren) {
1275 List<ExpandableNotificationRow> notificationChildren =
1276 mChildrenContainer.getNotificationChildren();
1277 for (int i = 0; i < notificationChildren.size(); i++) {
1278 ExpandableNotificationRow child = notificationChildren.get(i);
1279 child.updateNoBackgroundState();
1280 }
1281 }
1282 }
1283
1284 private void updateNoBackgroundState() {
1285 mShowNoBackground = isChildInGroup() && hasSameBgColor(mNotificationParent);
1286 updateBackground();
1287 }
1288
Chris Wren78403d72014-07-28 10:23:24 +01001289 public void setExpansionLogger(ExpansionLogger logger, String key) {
1290 mLogger = logger;
1291 mLoggingKey = key;
1292 }
1293
Selim Cinek6183d122016-01-14 18:48:41 -08001294 @Override
Selim Cinek61633a82016-01-25 15:54:10 -08001295 public boolean needsIncreasedPadding() {
1296 return mIsSummaryWithChildren && isGroupExpanded();
1297 }
1298
1299 @Override
Selim Cinek6183d122016-01-14 18:48:41 -08001300 protected boolean disallowSingleClick(MotionEvent event) {
1301 float x = event.getX();
1302 float y = event.getY();
Selim Cinek34eda5e2016-02-18 17:10:43 -08001303 NotificationHeaderView header = getVisibleNotificationHeader();
Selim Cinek6183d122016-01-14 18:48:41 -08001304 if (header != null) {
1305 return header.isInTouchRect(x, y);
1306 }
1307 return super.disallowSingleClick(event);
1308 }
1309
Chris Wren78403d72014-07-28 10:23:24 +01001310 private void logExpansionEvent(boolean userAction, boolean wasExpanded) {
1311 final boolean nowExpanded = isExpanded();
1312 if (wasExpanded != nowExpanded && mLogger != null) {
1313 mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded) ;
1314 }
1315 }
Selim Cinek570981d2015-12-01 11:37:01 -08001316
1317 public interface OnExpandClickListener {
Selim Cinek31aada42015-12-18 17:51:15 -08001318 void onExpandClicked(NotificationData.Entry clickedEntry, boolean nowExpanded);
Selim Cinek570981d2015-12-01 11:37:01 -08001319 }
Chris Wren51c75102013-07-16 20:49:17 -04001320}