blob: 210be9fe3505c8227d9ac276e06b7634b1111a6c [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 Cinekb5605e52015-02-20 18:21:41 +010019import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
21import android.animation.ValueAnimator;
Chris Wren51c75102013-07-16 20:49:17 -040022import android.content.Context;
Selim Cinekcab4a602014-09-03 14:47:57 +020023import android.graphics.drawable.AnimatedVectorDrawable;
24import android.graphics.drawable.AnimationDrawable;
Selim Cinekb5605e52015-02-20 18:21:41 +010025import android.graphics.drawable.ColorDrawable;
Selim Cinekcab4a602014-09-03 14:47:57 +020026import android.graphics.drawable.Drawable;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +020027import android.service.notification.StatusBarNotification;
Chris Wren51c75102013-07-16 20:49:17 -040028import android.util.AttributeSet;
Selim Cinek1a521f32014-11-03 17:39:29 +010029import android.view.MotionEvent;
Dan Sandlera5e0f412014-01-23 15:11:54 -050030import android.view.View;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +020031import android.view.ViewStub;
Jorim Jaggife40f7d2014-04-28 15:20:04 +020032import android.view.accessibility.AccessibilityEvent;
Selim Cinekb5605e52015-02-20 18:21:41 +010033import android.view.animation.LinearInterpolator;
Selim Cinekcab4a602014-09-03 14:47:57 +020034import android.widget.ImageView;
Selim Cinekb5605e52015-02-20 18:21:41 +010035
Dan Sandlera5e0f412014-01-23 15:11:54 -050036import com.android.systemui.R;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -070037import com.android.systemui.classifier.FalsingManager;
Selim Cinekb5605e52015-02-20 18:21:41 +010038import com.android.systemui.statusbar.phone.NotificationGroupManager;
39import com.android.systemui.statusbar.phone.PhoneStatusBar;
40import 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 /**
75 * Whether the notification expansion is disabled. This is the case on Keyguard.
76 */
77 private boolean mExpansionDisabled;
78
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 Cinekb5605e52015-02-20 18:21:41 +010091 private View mExpandButton;
92 private View mExpandButtonDivider;
93 private ViewStub mExpandButtonStub;
94 private ViewStub mChildrenContainerStub;
95 private NotificationGroupManager mGroupManager;
96 private View mExpandButtonContainer;
97 private boolean mChildrenExpanded;
98 private NotificationChildrenContainer mChildrenContainer;
99 private ValueAnimator mChildExpandAnimator;
100 private float mChildrenExpandProgress;
101 private float mExpandButtonStart;
Selim Cinekab29aeb2015-02-20 18:18:32 +0100102 private ViewStub mGutsStub;
Selim Cinekb5605e52015-02-20 18:21:41 +0100103 private boolean mHasExpandAction;
104 private boolean mIsSystemChildExpanded;
Selim Cinek684a4422015-04-15 16:18:39 -0700105 private boolean mIsPinned;
Selim Cinekb5605e52015-02-20 18:21:41 +0100106 private OnClickListener mExpandClickListener = new OnClickListener() {
107 @Override
108 public void onClick(View v) {
109 mGroupManager.setGroupExpanded(mStatusBarNotification,
110 !mChildrenExpanded);
111 }
112 };
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700113 private FalsingManager mFalsingManager;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200114
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700115 private boolean mJustClicked;
116
Selim Cinek8d490d42015-04-10 00:05:50 -0700117 public NotificationContentView getPrivateLayout() {
118 return mPrivateLayout;
119 }
120
121 public NotificationContentView getPublicLayout() {
122 return mPublicLayout;
123 }
124
Selim Cinekcab4a602014-09-03 14:47:57 +0200125 public void setIconAnimationRunning(boolean running) {
126 setIconAnimationRunning(running, mPublicLayout);
127 setIconAnimationRunning(running, mPrivateLayout);
128 }
129
130 private void setIconAnimationRunning(boolean running, NotificationContentView layout) {
131 if (layout != null) {
132 View contractedChild = layout.getContractedChild();
133 View expandedChild = layout.getExpandedChild();
Selim Cinek8d490d42015-04-10 00:05:50 -0700134 View headsUpChild = layout.getHeadsUpChild();
Selim Cinekcab4a602014-09-03 14:47:57 +0200135 setIconAnimationRunningForChild(running, contractedChild);
136 setIconAnimationRunningForChild(running, expandedChild);
Selim Cinek8d490d42015-04-10 00:05:50 -0700137 setIconAnimationRunningForChild(running, headsUpChild);
Selim Cinekcab4a602014-09-03 14:47:57 +0200138 }
139 }
140
141 private void setIconAnimationRunningForChild(boolean running, View child) {
142 if (child != null) {
143 ImageView icon = (ImageView) child.findViewById(com.android.internal.R.id.icon);
144 setIconRunning(icon, running);
145 ImageView rightIcon = (ImageView) child.findViewById(
146 com.android.internal.R.id.right_icon);
147 setIconRunning(rightIcon, running);
148 }
149 }
150
151 private void setIconRunning(ImageView imageView, boolean running) {
152 if (imageView != null) {
153 Drawable drawable = imageView.getDrawable();
154 if (drawable instanceof AnimationDrawable) {
155 AnimationDrawable animationDrawable = (AnimationDrawable) drawable;
156 if (running) {
157 animationDrawable.start();
158 } else {
159 animationDrawable.stop();
160 }
161 } else if (drawable instanceof AnimatedVectorDrawable) {
162 AnimatedVectorDrawable animationDrawable = (AnimatedVectorDrawable) drawable;
163 if (running) {
164 animationDrawable.start();
165 } else {
166 animationDrawable.stop();
167 }
168 }
169 }
170 }
171
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200172 public void setStatusBarNotification(StatusBarNotification statusBarNotification) {
173 mStatusBarNotification = statusBarNotification;
Selim Cineka37774f2014-11-11 19:16:18 +0100174 updateVetoButton();
Selim Cinekb5605e52015-02-20 18:21:41 +0100175 updateExpandButton();
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200176 }
177
178 public StatusBarNotification getStatusBarNotification() {
179 return mStatusBarNotification;
180 }
181
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700182 public boolean isHeadsUp() {
183 return mIsHeadsUp;
184 }
185
Selim Cinek1a521f32014-11-03 17:39:29 +0100186 public void setHeadsUp(boolean isHeadsUp) {
Selim Cinekc80fdb12015-04-13 15:09:08 -0700187 int intrinsicBefore = getIntrinsicHeight();
Selim Cinek1a521f32014-11-03 17:39:29 +0100188 mIsHeadsUp = isHeadsUp;
Selim Cinek8d490d42015-04-10 00:05:50 -0700189 mPrivateLayout.setHeadsUp(isHeadsUp);
Selim Cinekc80fdb12015-04-13 15:09:08 -0700190 if (intrinsicBefore != getIntrinsicHeight()) {
191 notifyHeightChanged(false /* needsAnimation */);
192 }
Selim Cinek1a521f32014-11-03 17:39:29 +0100193 }
194
Selim Cinekb5605e52015-02-20 18:21:41 +0100195 public void setGroupManager(NotificationGroupManager groupManager) {
196 mGroupManager = groupManager;
197 }
198
199 public void addChildNotification(ExpandableNotificationRow row) {
200 addChildNotification(row, -1);
201 }
202
203 /**
204 * Add a child notification to this view.
205 *
206 * @param row the row to add
207 * @param childIndex the index to add it at, if -1 it will be added at the end
208 */
209 public void addChildNotification(ExpandableNotificationRow row, int childIndex) {
210 if (mChildrenContainer == null) {
211 mChildrenContainerStub.inflate();
212 }
213 mChildrenContainer.addNotification(row, childIndex);
214 }
215
216 public void removeChildNotification(ExpandableNotificationRow row) {
217 if (mChildrenContainer != null) {
218 mChildrenContainer.removeNotification(row);
219 }
220 }
221
222 @Override
223 public boolean areChildrenExpanded() {
224 return mChildrenExpanded;
225 }
226
227 public List<ExpandableNotificationRow> getNotificationChildren() {
228 return mChildrenContainer == null ? null : mChildrenContainer.getNotificationChildren();
229 }
230
231 /**
232 * Apply the order given in the list to the children.
233 *
234 * @param childOrder the new list order
235 * @return whether the list order has changed
236 */
237 public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder) {
238 return mChildrenContainer != null && mChildrenContainer.applyChildOrder(childOrder);
239 }
240
241 public void getChildrenStates(StackScrollState resultState) {
242 if (mChildrenExpanded) {
243 StackViewState parentState = resultState.getViewStateForView(this);
244 mChildrenContainer.getState(resultState, parentState);
245 }
246 }
247
248 public void applyChildrenState(StackScrollState state) {
249 if (mChildrenExpanded) {
250 mChildrenContainer.applyState(state);
251 }
252 }
253
254 public void prepareExpansionChanged(StackScrollState state) {
255 if (mChildrenExpanded) {
256 mChildrenContainer.prepareExpansionChanged(state);
257 }
258 }
259
260 public void startChildAnimation(StackScrollState finalState,
261 StackStateAnimator stateAnimator, boolean withDelays, long delay, long duration) {
262 if (mChildrenExpanded) {
263 mChildrenContainer.startAnimationToState(finalState, stateAnimator, withDelays, delay,
264 duration);
265 }
266 }
267
268 public ExpandableNotificationRow getViewAtPosition(float y) {
269 if (!mChildrenExpanded) {
270 return this;
271 } else {
272 ExpandableNotificationRow view = mChildrenContainer.getViewAtPosition(y);
273 return view == null ? this : view;
274 }
275 }
276
Selim Cinekab29aeb2015-02-20 18:18:32 +0100277 public NotificationGuts getGuts() {
278 return mGuts;
279 }
280
Selim Cinekb5605e52015-02-20 18:21:41 +0100281 protected int calculateContentHeightFromActualHeight(int actualHeight) {
282 int realActualHeight = actualHeight;
283 if (hasBottomDecor()) {
284 realActualHeight -= getBottomDecorHeight();
285 }
286 realActualHeight = Math.max(getMinHeight(), realActualHeight);
287 return realActualHeight;
288 }
289
Selim Cinek684a4422015-04-15 16:18:39 -0700290 /**
291 * Set this notification to be pinned to the top if {@link #isHeadsUp()} is true. By doing this
292 * the notification will be rendered on top of the screen.
293 *
294 * @param pinned whether it is pinned
295 */
296 public void setPinned(boolean pinned) {
297 mIsPinned = pinned;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700298 }
299
Selim Cinek684a4422015-04-15 16:18:39 -0700300 public boolean isPinned() {
301 return mIsPinned;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700302 }
303
304 public int getHeadsUpHeight() {
Selim Cinek8d490d42015-04-10 00:05:50 -0700305 return mHeadsUpHeight;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700306 }
307
Jorim Jaggi5eb67c22015-08-19 19:50:49 -0700308 /**
309 * Mark whether this notification was just clicked, i.e. the user has just clicked this
310 * notification in this frame.
311 */
312 public void setJustClicked(boolean justClicked) {
313 mJustClicked = justClicked;
314 }
315
316 /**
317 * @return true if this notification has been clicked in this frame, false otherwise
318 */
319 public boolean wasJustClicked() {
320 return mJustClicked;
321 }
322
Chris Wren78403d72014-07-28 10:23:24 +0100323 public interface ExpansionLogger {
324 public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
325 }
Selim Cinek1685e632014-04-08 02:27:49 +0200326
Chris Wren51c75102013-07-16 20:49:17 -0400327 public ExpandableNotificationRow(Context context, AttributeSet attrs) {
328 super(context, attrs);
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700329 mFalsingManager = FalsingManager.getInstance(context);
Chris Wren51c75102013-07-16 20:49:17 -0400330 }
331
Christoph Studera7fe6312014-06-27 19:32:44 +0200332 /**
333 * Resets this view so it can be re-used for an updated notification.
334 */
Christoph Studer22f2ee52014-07-29 22:57:21 +0200335 @Override
Christoph Studera7fe6312014-06-27 19:32:44 +0200336 public void reset() {
Christoph Studer22f2ee52014-07-29 22:57:21 +0200337 super.reset();
Christoph Studera7fe6312014-06-27 19:32:44 +0200338 mRowMinHeight = 0;
Chris Wren78403d72014-07-28 10:23:24 +0100339 final boolean wasExpanded = isExpanded();
Selim Cinek379ff8f2015-02-20 17:03:16 +0100340 mMaxViewHeight = 0;
Christoph Studera7fe6312014-06-27 19:32:44 +0200341 mExpandable = false;
342 mHasUserChangedExpansion = false;
343 mUserLocked = false;
344 mShowingPublic = false;
Jorim Jaggiae441282014-08-01 02:45:18 +0200345 mSensitive = false;
346 mShowingPublicInitialized = false;
Christoph Studera7fe6312014-06-27 19:32:44 +0200347 mIsSystemExpanded = false;
348 mExpansionDisabled = false;
Selim Cinek1a521f32014-11-03 17:39:29 +0100349 mPublicLayout.reset(mIsHeadsUp);
350 mPrivateLayout.reset(mIsHeadsUp);
Selim Cinek31094df2014-08-14 19:28:15 +0200351 resetHeight();
352 logExpansionEvent(false, wasExpanded);
353 }
354
355 public void resetHeight() {
Selim Cinek1a521f32014-11-03 17:39:29 +0100356 if (mIsHeadsUp) {
357 resetActualHeight();
358 }
Christoph Studera7fe6312014-06-27 19:32:44 +0200359 mMaxExpandHeight = 0;
Selim Cinek8d490d42015-04-10 00:05:50 -0700360 mHeadsUpHeight = 0;
Selim Cineka5e211b2014-08-11 17:35:48 +0200361 mWasReset = true;
Selim Cinek31094df2014-08-14 19:28:15 +0200362 onHeightReset();
Selim Cinek6e28a672014-09-05 14:43:28 +0200363 requestLayout();
Christoph Studera7fe6312014-06-27 19:32:44 +0200364 }
365
Jorim Jaggi251957d2014-04-09 04:24:09 +0200366 @Override
Selim Cinek1a521f32014-11-03 17:39:29 +0100367 protected boolean filterMotionEvent(MotionEvent event) {
368 return mIsHeadsUp || super.filterMotionEvent(event);
369 }
370
371 @Override
Jorim Jaggi251957d2014-04-09 04:24:09 +0200372 protected void onFinishInflate() {
373 super.onFinishInflate();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200374 mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
375 mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
Selim Cinekab29aeb2015-02-20 18:18:32 +0100376 mGutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
377 mGutsStub.setOnInflateListener(new ViewStub.OnInflateListener() {
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200378 @Override
379 public void onInflate(ViewStub stub, View inflated) {
380 mGuts = (NotificationGuts) inflated;
381 mGuts.setClipTopAmount(getClipTopAmount());
382 mGuts.setActualHeight(getActualHeight());
Selim Cinekab29aeb2015-02-20 18:18:32 +0100383 mGutsStub = null;
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200384 }
385 });
Selim Cinekb5605e52015-02-20 18:21:41 +0100386 mExpandButtonStub = (ViewStub) findViewById(R.id.more_button_stub);
387 mExpandButtonStub.setOnInflateListener(new ViewStub.OnInflateListener() {
388
389 @Override
390 public void onInflate(ViewStub stub, View inflated) {
391 mExpandButtonContainer = inflated;
392 mExpandButton = inflated.findViewById(R.id.notification_expand_button);
393 mExpandButtonDivider = inflated.findViewById(R.id.notification_expand_divider);
394 mExpandButtonContainer.setOnClickListener(mExpandClickListener);
395 }
396 });
397 mChildrenContainerStub = (ViewStub) findViewById(R.id.child_container_stub);
398 mChildrenContainerStub.setOnInflateListener(new ViewStub.OnInflateListener() {
399
400 @Override
401 public void onInflate(ViewStub stub, View inflated) {
402 mChildrenContainer = (NotificationChildrenContainer) inflated;
403 mChildrenContainer.setCollapseClickListener(mExpandClickListener);
404 updateChildrenVisibility(false);
405 }
406 });
Selim Cinek863834b2014-05-20 04:20:25 +0200407 mVetoButton = findViewById(R.id.veto);
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200408 }
409
Selim Cinekab29aeb2015-02-20 18:18:32 +0100410 public void inflateGuts() {
411 if (mGuts == null) {
412 mGutsStub.inflate();
413 }
414 }
415
Selim Cinekb5605e52015-02-20 18:21:41 +0100416 private void updateChildrenVisibility(boolean animated) {
417 if (mChildrenContainer == null) {
418 return;
419 }
420 if (mChildExpandAnimator != null) {
421 mChildExpandAnimator.cancel();
422 }
423 float targetProgress = mChildrenExpanded ? 1.0f : 0.0f;
424 if (animated) {
425 if (mChildrenExpanded) {
426 mChildrenContainer.setVisibility(VISIBLE);
427 }
428 mExpandButtonStart = mExpandButtonContainer.getTranslationY();
429 mChildExpandAnimator = ValueAnimator.ofFloat(mChildrenExpandProgress, targetProgress);
430 mChildExpandAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
431 @Override
432 public void onAnimationUpdate(ValueAnimator animation) {
433 setChildrenExpandProgress((float) animation.getAnimatedValue());
434 }
435 });
436 mChildExpandAnimator.addListener(new AnimatorListenerAdapter() {
437 @Override
438 public void onAnimationEnd(Animator animation) {
439 mChildExpandAnimator = null;
440 if (!mChildrenExpanded) {
441 mChildrenContainer.setVisibility(INVISIBLE);
442 }
443 }
444 });
445 mChildExpandAnimator.setInterpolator(mLinearInterpolator);
446 mChildExpandAnimator.setDuration(
447 StackStateAnimator.ANIMATION_DURATION_EXPAND_CLICKED);
448 mChildExpandAnimator.start();
449 } else {
450 setChildrenExpandProgress(targetProgress);
451 mChildrenContainer.setVisibility(mChildrenExpanded ? VISIBLE : INVISIBLE);
452 }
453 }
454
455 private void setChildrenExpandProgress(float progress) {
456 mChildrenExpandProgress = progress;
457 updateExpandButtonAppearance();
458 NotificationContentView showingLayout = getShowingLayout();
459 float alpha = 1.0f - mChildrenExpandProgress;
460 alpha = PhoneStatusBar.ALPHA_OUT.getInterpolation(alpha);
461 showingLayout.setAlpha(alpha);
462 }
463
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200464 @Override
Alan Viverettea54956a2015-01-07 16:05:02 -0800465 public boolean onRequestSendAccessibilityEventInternal(View child, AccessibilityEvent event) {
466 if (super.onRequestSendAccessibilityEventInternal(child, event)) {
Jorim Jaggife40f7d2014-04-28 15:20:04 +0200467 // Add a record for the entire layout since its content is somehow small.
468 // The event comes from a leaf view that is interacted with.
469 AccessibilityEvent record = AccessibilityEvent.obtain();
470 onInitializeAccessibilityEvent(record);
471 dispatchPopulateAccessibilityEvent(record);
472 event.appendRecord(record);
473 return true;
474 }
475 return false;
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200476 }
Chris Wren51c75102013-07-16 20:49:17 -0400477
John Spurlocke15452b2014-08-21 09:44:39 -0400478 @Override
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100479 public void setDark(boolean dark, boolean fade, long delay) {
480 super.setDark(dark, fade, delay);
John Spurlocke15452b2014-08-21 09:44:39 -0400481 final NotificationContentView showing = getShowingLayout();
482 if (showing != null) {
Jorim Jaggi4e857f42014-11-17 19:14:04 +0100483 showing.setDark(dark, fade, delay);
John Spurlocke15452b2014-08-21 09:44:39 -0400484 }
485 }
486
Selim Cinek1685e632014-04-08 02:27:49 +0200487 public void setHeightRange(int rowMinHeight, int rowMaxHeight) {
488 mRowMinHeight = rowMinHeight;
Selim Cinek379ff8f2015-02-20 17:03:16 +0100489 mMaxViewHeight = rowMaxHeight;
Chris Wren51c75102013-07-16 20:49:17 -0400490 }
491
492 public boolean isExpandable() {
493 return mExpandable;
494 }
495
496 public void setExpandable(boolean expandable) {
497 mExpandable = expandable;
498 }
499
Selim Cinek1685e632014-04-08 02:27:49 +0200500 /**
501 * @return whether the user has changed the expansion state
502 */
503 public boolean hasUserChangedExpansion() {
504 return mHasUserChangedExpansion;
505 }
506
Chris Wren51c75102013-07-16 20:49:17 -0400507 public boolean isUserExpanded() {
508 return mUserExpanded;
509 }
510
Selim Cinek1685e632014-04-08 02:27:49 +0200511 /**
512 * Set this notification to be expanded by the user
513 *
514 * @param userExpanded whether the user wants this notification to be expanded
515 */
Chris Wren51c75102013-07-16 20:49:17 -0400516 public void setUserExpanded(boolean userExpanded) {
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700517 mFalsingManager.setNotificationExpanded();
Christoph Studera7fe6312014-06-27 19:32:44 +0200518 if (userExpanded && !mExpandable) return;
Chris Wren78403d72014-07-28 10:23:24 +0100519 final boolean wasExpanded = isExpanded();
Selim Cinek1685e632014-04-08 02:27:49 +0200520 mHasUserChangedExpansion = true;
Chris Wren51c75102013-07-16 20:49:17 -0400521 mUserExpanded = userExpanded;
Chris Wren78403d72014-07-28 10:23:24 +0100522 logExpansionEvent(true, wasExpanded);
Chris Wren51c75102013-07-16 20:49:17 -0400523 }
524
Selim Cinekccd14fb2014-08-12 18:53:24 +0200525 public void resetUserExpansion() {
526 mHasUserChangedExpansion = false;
527 mUserExpanded = false;
528 }
529
Chris Wren51c75102013-07-16 20:49:17 -0400530 public boolean isUserLocked() {
531 return mUserLocked;
532 }
533
534 public void setUserLocked(boolean userLocked) {
535 mUserLocked = userLocked;
536 }
537
Selim Cinek1685e632014-04-08 02:27:49 +0200538 /**
539 * @return has the system set this notification to be expanded
540 */
541 public boolean isSystemExpanded() {
542 return mIsSystemExpanded;
543 }
544
545 /**
546 * Set this notification to be expanded by the system.
547 *
548 * @param expand whether the system wants this notification to be expanded.
549 */
550 public void setSystemExpanded(boolean expand) {
Selim Cinek31094df2014-08-14 19:28:15 +0200551 if (expand != mIsSystemExpanded) {
552 final boolean wasExpanded = isExpanded();
553 mIsSystemExpanded = expand;
Selim Cinekb5605e52015-02-20 18:21:41 +0100554 notifyHeightChanged(false /* needsAnimation */);
Selim Cinek31094df2014-08-14 19:28:15 +0200555 logExpansionEvent(false, wasExpanded);
556 }
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200557 }
558
559 /**
560 * @param expansionDisabled whether to prevent notification expansion
561 */
562 public void setExpansionDisabled(boolean expansionDisabled) {
Selim Cinek31094df2014-08-14 19:28:15 +0200563 if (expansionDisabled != mExpansionDisabled) {
564 final boolean wasExpanded = isExpanded();
565 mExpansionDisabled = expansionDisabled;
566 logExpansionEvent(false, wasExpanded);
567 if (wasExpanded != isExpanded()) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100568 notifyHeightChanged(false /* needsAnimation */);
Selim Cinek31094df2014-08-14 19:28:15 +0200569 }
570 }
Selim Cinek1685e632014-04-08 02:27:49 +0200571 }
572
573 /**
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400574 * @return Can the underlying notification be cleared?
575 */
576 public boolean isClearable() {
Selim Cineka37774f2014-11-11 19:16:18 +0100577 return mStatusBarNotification != null && mStatusBarNotification.isClearable();
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400578 }
579
580 /**
Selim Cinek1685e632014-04-08 02:27:49 +0200581 * Apply an expansion state to the layout.
Selim Cinek1685e632014-04-08 02:27:49 +0200582 */
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200583 public void applyExpansionToLayout() {
584 boolean expand = isExpanded();
Chris Wren51c75102013-07-16 20:49:17 -0400585 if (expand && mExpandable) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100586 setContentHeight(mMaxExpandHeight);
Chris Wren51c75102013-07-16 20:49:17 -0400587 } else {
Selim Cinekb5605e52015-02-20 18:21:41 +0100588 setContentHeight(mRowMinHeight);
Chris Wren51c75102013-07-16 20:49:17 -0400589 }
Chris Wren51c75102013-07-16 20:49:17 -0400590 }
Dan Sandlera5e0f412014-01-23 15:11:54 -0500591
Jorim Jaggi9cbadd32014-05-01 20:18:31 +0200592 @Override
593 public int getIntrinsicHeight() {
Jorim Jaggibe565df2014-04-28 17:51:23 +0200594 if (isUserLocked()) {
595 return getActualHeight();
596 }
Selim Cinek1685e632014-04-08 02:27:49 +0200597 boolean inExpansionState = isExpanded();
Selim Cinekb5605e52015-02-20 18:21:41 +0100598 int maxContentHeight;
Selim Cinek60122be2015-04-15 18:16:50 -0700599 if (mSensitive && mHideSensitiveForIntrinsicHeight) {
600 return mRowMinHeight;
601 } else if (mIsHeadsUp) {
Selim Cinek8d490d42015-04-10 00:05:50 -0700602 if (inExpansionState) {
603 maxContentHeight = Math.max(mMaxExpandHeight, mHeadsUpHeight);
604 } else {
605 maxContentHeight = Math.max(mRowMinHeight, mHeadsUpHeight);
606 }
Selim Cinek60122be2015-04-15 18:16:50 -0700607 } else if ((!inExpansionState && !mChildrenExpanded)) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100608 maxContentHeight = mRowMinHeight;
609 } else if (mChildrenExpanded) {
610 maxContentHeight = mChildrenContainer.getIntrinsicHeight();
611 } else {
612 maxContentHeight = getMaxExpandHeight();
Selim Cinek1685e632014-04-08 02:27:49 +0200613 }
Selim Cinekb5605e52015-02-20 18:21:41 +0100614 return maxContentHeight + getBottomDecorHeight();
615 }
Selim Cinek1685e632014-04-08 02:27:49 +0200616
Selim Cinekb5605e52015-02-20 18:21:41 +0100617 @Override
618 protected boolean hasBottomDecor() {
619 return BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS
620 && !mIsHeadsUp && mGroupManager.hasGroupChildren(mStatusBarNotification);
621 }
622
623 @Override
624 protected boolean canHaveBottomDecor() {
625 return BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS && !mIsHeadsUp;
Selim Cinek1685e632014-04-08 02:27:49 +0200626 }
627
Selim Cinek1685e632014-04-08 02:27:49 +0200628 /**
629 * Check whether the view state is currently expanded. This is given by the system in {@link
630 * #setSystemExpanded(boolean)} and can be overridden by user expansion or
631 * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this
632 * view can differ from this state, if layout params are modified from outside.
633 *
634 * @return whether the view state is currently expanded.
635 */
636 private boolean isExpanded() {
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200637 return !mExpansionDisabled
Selim Cinekb5605e52015-02-20 18:21:41 +0100638 && (!hasUserChangedExpansion() && (isSystemExpanded() || isSystemChildExpanded())
639 || isUserExpanded());
640 }
641
642 private boolean isSystemChildExpanded() {
643 return mIsSystemChildExpanded;
644 }
645
646 public void setSystemChildExpanded(boolean expanded) {
647 mIsSystemChildExpanded = expanded;
Selim Cinek1685e632014-04-08 02:27:49 +0200648 }
649
650 @Override
651 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
652 super.onLayout(changed, left, top, right, bottom);
Selim Cineka5e211b2014-08-11 17:35:48 +0200653 boolean updateExpandHeight = mMaxExpandHeight == 0 && !mWasReset;
Selim Cinek8d490d42015-04-10 00:05:50 -0700654 updateMaxHeights();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200655 if (updateExpandHeight) {
Jorim Jaggidce3c4c2014-04-29 23:12:24 +0200656 applyExpansionToLayout();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200657 }
Selim Cineka5e211b2014-08-11 17:35:48 +0200658 mWasReset = false;
Selim Cinek1685e632014-04-08 02:27:49 +0200659 }
660
Selim Cinekb5605e52015-02-20 18:21:41 +0100661 @Override
662 protected boolean isChildInvisible(View child) {
663
664 // We don't want to layout the ChildrenContainer if this is a heads-up view, otherwise the
665 // view will get too high and the shadows will be off.
666 boolean isInvisibleChildContainer = child == mChildrenContainer && mIsHeadsUp;
667 return super.isChildInvisible(child) || isInvisibleChildContainer;
668 }
669
Selim Cinek8d490d42015-04-10 00:05:50 -0700670 private void updateMaxHeights() {
Selim Cinekd2319fb2014-09-01 19:41:54 +0200671 int intrinsicBefore = getIntrinsicHeight();
Selim Cinek8d490d42015-04-10 00:05:50 -0700672 View expandedChild = mPrivateLayout.getExpandedChild();
673 if (expandedChild == null) {
674 expandedChild = mPrivateLayout.getContractedChild();
675 }
676 mMaxExpandHeight = expandedChild.getHeight();
677 View headsUpChild = mPrivateLayout.getHeadsUpChild();
Selim Cinek1f3f5442015-04-10 17:54:46 -0700678 if (headsUpChild == null) {
679 headsUpChild = mPrivateLayout.getContractedChild();
Selim Cinek8d490d42015-04-10 00:05:50 -0700680 }
Selim Cinek1f3f5442015-04-10 17:54:46 -0700681 mHeadsUpHeight = headsUpChild.getHeight();
Selim Cinekd2319fb2014-09-01 19:41:54 +0200682 if (intrinsicBefore != getIntrinsicHeight()) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100683 notifyHeightChanged(false /* needsAnimation */);
Selim Cinekd2319fb2014-09-01 19:41:54 +0200684 }
685 }
686
Jorim Jaggiae441282014-08-01 02:45:18 +0200687 public void setSensitive(boolean sensitive) {
688 mSensitive = sensitive;
689 }
690
691 public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) {
Selim Cinek60122be2015-04-15 18:16:50 -0700692 mHideSensitiveForIntrinsicHeight = hideSensitive;
Jorim Jaggiae441282014-08-01 02:45:18 +0200693 }
694
695 public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
696 long duration) {
697 boolean oldShowingPublic = mShowingPublic;
698 mShowingPublic = mSensitive && hideSensitive;
699 if (mShowingPublicInitialized && mShowingPublic == oldShowingPublic) {
700 return;
701 }
Dan Sandlera5e0f412014-01-23 15:11:54 -0500702
703 // bail out if no public version
Selim Cinek1685e632014-04-08 02:27:49 +0200704 if (mPublicLayout.getChildCount() == 0) return;
Dan Sandlera5e0f412014-01-23 15:11:54 -0500705
Jorim Jaggiae441282014-08-01 02:45:18 +0200706 if (!animated) {
707 mPublicLayout.animate().cancel();
708 mPrivateLayout.animate().cancel();
709 mPublicLayout.setAlpha(1f);
710 mPrivateLayout.setAlpha(1f);
711 mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE);
712 mPrivateLayout.setVisibility(mShowingPublic ? View.INVISIBLE : View.VISIBLE);
713 } else {
714 animateShowingPublic(delay, duration);
715 }
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400716
717 updateVetoButton();
Jorim Jaggiae441282014-08-01 02:45:18 +0200718 mShowingPublicInitialized = true;
719 }
720
721 private void animateShowingPublic(long delay, long duration) {
722 final View source = mShowingPublic ? mPrivateLayout : mPublicLayout;
723 View target = mShowingPublic ? mPublicLayout : mPrivateLayout;
724 source.setVisibility(View.VISIBLE);
725 target.setVisibility(View.VISIBLE);
726 target.setAlpha(0f);
727 source.animate().cancel();
728 target.animate().cancel();
729 source.animate()
730 .alpha(0f)
Jorim Jaggiae441282014-08-01 02:45:18 +0200731 .setStartDelay(delay)
732 .setDuration(duration)
733 .withEndAction(new Runnable() {
734 @Override
735 public void run() {
736 source.setVisibility(View.INVISIBLE);
737 }
738 });
739 target.animate()
740 .alpha(1f)
Jorim Jaggiae441282014-08-01 02:45:18 +0200741 .setStartDelay(delay)
742 .setDuration(duration);
Dan Sandler0d3e62f2014-07-14 17:13:50 -0400743 }
744
745 private void updateVetoButton() {
746 // public versions cannot be dismissed
747 mVetoButton.setVisibility(isClearable() && !mShowingPublic ? View.VISIBLE : View.GONE);
Dan Sandlera5e0f412014-01-23 15:11:54 -0500748 }
Jorim Jaggi251957d2014-04-09 04:24:09 +0200749
Selim Cinekb5605e52015-02-20 18:21:41 +0100750 public void setChildrenExpanded(boolean expanded, boolean animate) {
751 mChildrenExpanded = expanded;
752 updateChildrenVisibility(animate);
753 }
754
755 public void updateExpandButton() {
756 boolean hasExpand = hasBottomDecor();
757 if (hasExpand != mHasExpandAction) {
758 if (hasExpand) {
759 if (mExpandButtonContainer == null) {
760 mExpandButtonStub.inflate();
761 }
762 mExpandButtonContainer.setVisibility(View.VISIBLE);
763 updateExpandButtonAppearance();
764 updateExpandButtonColor();
765 } else if (mExpandButtonContainer != null) {
766 mExpandButtonContainer.setVisibility(View.GONE);
767 }
768 notifyHeightChanged(true /* needsAnimation */);
769 }
770 mHasExpandAction = hasExpand;
771 }
772
773 private void updateExpandButtonAppearance() {
774 if (mExpandButtonContainer == null) {
775 return;
776 }
777 float expandButtonAlpha = 0.0f;
778 float expandButtonTranslation = 0.0f;
779 float containerTranslation = 0.0f;
780 int minHeight = getMinHeight();
781 if (!mChildrenExpanded || mChildExpandAnimator != null) {
782 int expandActionHeight = getBottomDecorHeight();
783 int translationY = getActualHeight() - expandActionHeight;
784 if (translationY > minHeight) {
785 containerTranslation = translationY;
786 expandButtonAlpha = 1.0f;
787 expandButtonTranslation = 0.0f;
788 } else {
789 containerTranslation = minHeight;
790 float progress = expandActionHeight != 0
791 ? (minHeight - translationY) / (float) expandActionHeight
792 : 1.0f;
793 expandButtonTranslation = -progress * expandActionHeight * 0.7f;
794 float alphaProgress = Math.min(progress / 0.7f, 1.0f);
795 alphaProgress = PhoneStatusBar.ALPHA_OUT.getInterpolation(alphaProgress);
796 expandButtonAlpha = 1.0f - alphaProgress;
797 }
798 }
799 if (mChildExpandAnimator != null || mChildrenExpanded) {
800 expandButtonAlpha = (1.0f - mChildrenExpandProgress)
801 * expandButtonAlpha;
802 expandButtonTranslation = (1.0f - mChildrenExpandProgress)
803 * expandButtonTranslation;
804 float newTranslation = -getBottomDecorHeight();
805
806 // We don't want to take the actual height of the view as this is already
807 // interpolated by a custom interpolator leading to a confusing animation. We want
808 // to have a stable end value to interpolate in between
809 float collapsedHeight = !mChildrenExpanded
810 ? Math.max(StackStateAnimator.getFinalActualHeight(this)
811 - getBottomDecorHeight(), minHeight)
812 : mExpandButtonStart;
813 float translationProgress = mFastOutSlowInInterpolator.getInterpolation(
814 mChildrenExpandProgress);
815 containerTranslation = (1.0f - translationProgress) * collapsedHeight
816 + translationProgress * newTranslation;
817 }
818 mExpandButton.setAlpha(expandButtonAlpha);
819 mExpandButtonDivider.setAlpha(expandButtonAlpha);
820 mExpandButton.setTranslationY(expandButtonTranslation);
821 mExpandButtonContainer.setTranslationY(containerTranslation);
822 NotificationContentView showingLayout = getShowingLayout();
823 float layoutTranslation =
824 mExpandButtonContainer.getTranslationY() - showingLayout.getContentHeight();
825 layoutTranslation = Math.min(layoutTranslation, 0);
826 if (!mChildrenExpanded && mChildExpandAnimator == null) {
827 // Needed for the DragDownHelper in order not to jump there, as the position
828 // can be negative for a short time.
829 layoutTranslation = 0;
830 }
831 showingLayout.setTranslationY(layoutTranslation);
832 if (mChildrenContainer != null) {
833 mChildrenContainer.setTranslationY(
834 mExpandButtonContainer.getTranslationY() + getBottomDecorHeight());
835 }
836 }
837
838 private void updateExpandButtonColor() {
839 // TODO: This needs some more baking, currently only the divider is colored according to
840 // the tint, but legacy black doesn't work yet perfectly for the button etc.
841 int color = getRippleColor();
842 if (color == mNormalRippleColor) {
843 color = 0;
844 }
845 if (mExpandButtonDivider != null) {
846 applyTint(mExpandButtonDivider, color);
847 }
848 if (mChildrenContainer != null) {
849 mChildrenContainer.setTintColor(color);
850 }
851 }
852
853 public static void applyTint(View v, int color) {
854 int alpha;
855 if (color != 0) {
856 alpha = COLORED_DIVIDER_ALPHA;
857 } else {
858 color = 0xff000000;
859 alpha = DEFAULT_DIVIDER_ALPHA;
860 }
861 if (v.getBackground() instanceof ColorDrawable) {
862 ColorDrawable background = (ColorDrawable) v.getBackground();
863 background.mutate();
864 background.setColor(color);
865 background.setAlpha(alpha);
866 }
867 }
868
Selim Cinek1685e632014-04-08 02:27:49 +0200869 public int getMaxExpandHeight() {
Selim Cinekb5605e52015-02-20 18:21:41 +0100870 return mMaxExpandHeight;
Chris Wren51c75102013-07-16 20:49:17 -0400871 }
Jorim Jaggi584a7aa2014-04-10 23:26:13 +0200872
Jorim Jaggibe565df2014-04-28 17:51:23 +0200873 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200874 public boolean isContentExpandable() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200875 NotificationContentView showingLayout = getShowingLayout();
876 return showingLayout.isContentExpandable();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200877 }
878
879 @Override
Selim Cinek560e64d2015-06-09 19:58:11 -0700880 protected View getContentView() {
881 return getShowingLayout();
882 }
883
884 @Override
Jorim Jaggid552d9d2014-05-07 19:41:13 +0200885 public void setActualHeight(int height, boolean notifyListeners) {
Selim Cinekb5605e52015-02-20 18:21:41 +0100886 super.setActualHeight(height, notifyListeners);
887 int contentHeight = calculateContentHeightFromActualHeight(height);
888 mPrivateLayout.setContentHeight(contentHeight);
889 mPublicLayout.setContentHeight(contentHeight);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200890 if (mGuts != null) {
891 mGuts.setActualHeight(height);
892 }
Jorim Jaggibe565df2014-04-28 17:51:23 +0200893 invalidate();
Selim Cinekb5605e52015-02-20 18:21:41 +0100894 updateExpandButtonAppearance();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200895 }
896
897 @Override
Selim Cinekb5605e52015-02-20 18:21:41 +0100898 public int getMaxContentHeight() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200899 NotificationContentView showingLayout = getShowingLayout();
900 return showingLayout.getMaxHeight();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200901 }
902
903 @Override
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200904 public int getMinHeight() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200905 NotificationContentView showingLayout = getShowingLayout();
906 return showingLayout.getMinHeight();
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200907 }
908
909 @Override
Jorim Jaggibe565df2014-04-28 17:51:23 +0200910 public void setClipTopAmount(int clipTopAmount) {
911 super.setClipTopAmount(clipTopAmount);
912 mPrivateLayout.setClipTopAmount(clipTopAmount);
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200913 mPublicLayout.setClipTopAmount(clipTopAmount);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +0200914 if (mGuts != null) {
915 mGuts.setClipTopAmount(clipTopAmount);
916 }
Jorim Jaggibe565df2014-04-28 17:51:23 +0200917 }
918
919 public void notifyContentUpdated() {
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200920 mPublicLayout.notifyContentUpdated();
Jorim Jaggibe565df2014-04-28 17:51:23 +0200921 mPrivateLayout.notifyContentUpdated();
Selim Cinek343e6e22014-04-11 21:23:30 +0200922 }
Selim Cinek7d447722014-06-10 15:51:59 +0200923
Selim Cinek31094df2014-08-14 19:28:15 +0200924 public boolean isMaxExpandHeightInitialized() {
925 return mMaxExpandHeight != 0;
Selim Cinek7d447722014-06-10 15:51:59 +0200926 }
Selim Cinek2f0df8a2014-06-10 17:40:42 +0200927
928 private NotificationContentView getShowingLayout() {
929 return mShowingPublic ? mPublicLayout : mPrivateLayout;
930 }
Chris Wren78403d72014-07-28 10:23:24 +0100931
Jorim Jaggi59ec3042015-06-05 15:18:43 -0700932 @Override
933 public void setShowingLegacyBackground(boolean showing) {
934 super.setShowingLegacyBackground(showing);
935 mPrivateLayout.setShowingLegacyBackground(showing);
936 mPublicLayout.setShowingLegacyBackground(showing);
937 }
938
Chris Wren78403d72014-07-28 10:23:24 +0100939 public void setExpansionLogger(ExpansionLogger logger, String key) {
940 mLogger = logger;
941 mLoggingKey = key;
942 }
943
Chris Wren78403d72014-07-28 10:23:24 +0100944 private void logExpansionEvent(boolean userAction, boolean wasExpanded) {
945 final boolean nowExpanded = isExpanded();
946 if (wasExpanded != nowExpanded && mLogger != null) {
947 mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded) ;
948 }
949 }
Chris Wren51c75102013-07-16 20:49:17 -0400950}