blob: 2da2724aacb200597abbfebecb1a08037506f163 [file] [log] [blame]
Selim Cinekdf5bf612016-02-26 09:56:31 -08001/*
2 * Copyright (C) 2016 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
Rohan Shah20790b82018-07-02 17:21:04 -070017package com.android.systemui.statusbar.notification.row.wrapper;
Selim Cinekdf5bf612016-02-26 09:56:31 -080018
Beth Thibodeaucb395352019-01-25 15:39:54 -050019import static com.android.systemui.Dependency.MAIN_HANDLER;
Selim Cinekdf5bf612016-02-26 09:56:31 -080020
Beth Thibodeau2e76ad52019-05-29 11:29:25 -040021import android.annotation.Nullable;
Beth Thibodeaucb395352019-01-25 15:39:54 -050022import android.app.Notification;
23import android.content.Context;
24import android.content.res.ColorStateList;
25import android.media.MediaMetadata;
26import android.media.session.MediaController;
27import android.media.session.MediaSession;
28import android.media.session.PlaybackState;
Beth Thibodeau4b05fbc2019-05-16 12:51:20 -040029import android.metrics.LogMaker;
Beth Thibodeaucb395352019-01-25 15:39:54 -050030import android.os.Handler;
Beth Thibodeau899b5952020-01-07 17:50:07 -050031import android.service.notification.StatusBarNotification;
Beth Thibodeaucb395352019-01-25 15:39:54 -050032import android.text.format.DateUtils;
Beth Thibodeaucb395352019-01-25 15:39:54 -050033import android.view.LayoutInflater;
34import android.view.View;
35import android.view.ViewStub;
36import android.widget.SeekBar;
37import android.widget.TextView;
38
39import com.android.internal.R;
Beth Thibodeau4b05fbc2019-05-16 12:51:20 -040040import com.android.internal.annotations.VisibleForTesting;
41import com.android.internal.logging.MetricsLogger;
42import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Beth Thibodeau4e4c86e2019-08-01 10:57:29 -040043import com.android.internal.widget.MediaNotificationView;
Beth Thibodeaucb395352019-01-25 15:39:54 -050044import com.android.systemui.Dependency;
Beth Thibodeau07d20c32019-10-16 13:45:56 -040045import com.android.systemui.qs.QSPanel;
46import com.android.systemui.qs.QuickQSPanel;
Beth Thibodeaueab4dde2019-02-07 11:37:02 -050047import com.android.systemui.statusbar.NotificationMediaManager;
Selim Cinekdf5bf612016-02-26 09:56:31 -080048import com.android.systemui.statusbar.TransformableView;
Gus Prevasab336792018-11-14 13:52:20 -050049import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
wilsonshihe8321942019-10-18 18:39:46 +080050import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
Matt Pietal5a19cb62019-10-30 12:31:07 -040051import com.android.systemui.util.Utils;
Selim Cinekdf5bf612016-02-26 09:56:31 -080052
Beth Thibodeaucb395352019-01-25 15:39:54 -050053import java.util.Timer;
54import java.util.TimerTask;
55
Selim Cinekdf5bf612016-02-26 09:56:31 -080056/**
57 * Wraps a notification containing a media template
58 */
59public class NotificationMediaTemplateViewWrapper extends NotificationTemplateViewWrapper {
60
Beth Thibodeaucb395352019-01-25 15:39:54 -050061 private static final long PROGRESS_UPDATE_INTERVAL = 1000; // 1s
62 private static final String COMPACT_MEDIA_TAG = "media";
63 private final Handler mHandler = Dependency.get(MAIN_HANDLER);
64 private Timer mSeekBarTimer;
65 private View mActions;
66 private SeekBar mSeekBar;
67 private TextView mSeekBarElapsedTime;
68 private TextView mSeekBarTotalTime;
69 private long mDuration = 0;
70 private MediaController mMediaController;
Beth Thibodeau2e76ad52019-05-29 11:29:25 -040071 private MediaMetadata mMediaMetadata;
Beth Thibodeaueab4dde2019-02-07 11:37:02 -050072 private NotificationMediaManager mMediaManager;
Beth Thibodeaucb395352019-01-25 15:39:54 -050073 private View mSeekBarView;
74 private Context mContext;
Beth Thibodeau4b05fbc2019-05-16 12:51:20 -040075 private MetricsLogger mMetricsLogger;
Beth Thibodeau4e4c86e2019-08-01 10:57:29 -040076 private boolean mIsViewVisible;
Beth Thibodeaucb395352019-01-25 15:39:54 -050077
Beth Thibodeau4b05fbc2019-05-16 12:51:20 -040078 @VisibleForTesting
79 protected SeekBar.OnSeekBarChangeListener mSeekListener =
80 new SeekBar.OnSeekBarChangeListener() {
Beth Thibodeaucb395352019-01-25 15:39:54 -050081 @Override
82 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
83 }
84
85 @Override
86 public void onStartTrackingTouch(SeekBar seekBar) {
87 }
88
89 @Override
90 public void onStopTrackingTouch(SeekBar seekBar) {
Beth Thibodeau2e76ad52019-05-29 11:29:25 -040091 if (mMediaController != null) {
Beth Thibodeaucb395352019-01-25 15:39:54 -050092 mMediaController.getTransportControls().seekTo(mSeekBar.getProgress());
Beth Thibodeau4b05fbc2019-05-16 12:51:20 -040093 mMetricsLogger.write(newLog(MetricsEvent.TYPE_UPDATE));
Beth Thibodeaucb395352019-01-25 15:39:54 -050094 }
95 }
96 };
97
Beth Thibodeau4e4c86e2019-08-01 10:57:29 -040098 private MediaNotificationView.VisibilityChangeListener mVisibilityListener =
99 new MediaNotificationView.VisibilityChangeListener() {
100 @Override
101 public void onAggregatedVisibilityChanged(boolean isVisible) {
102 mIsViewVisible = isVisible;
103 if (isVisible && mMediaController != null) {
104 // Restart timer if we're currently playing and didn't already have one going
105 PlaybackState state = mMediaController.getPlaybackState();
106 if (state != null && state.getState() == PlaybackState.STATE_PLAYING
107 && mSeekBarTimer == null && mSeekBarView != null
108 && mSeekBarView.getVisibility() != View.GONE) {
109 startTimer();
110 }
111 } else {
112 clearTimer();
113 }
114 }
115 };
116
117 private View.OnAttachStateChangeListener mAttachStateListener =
118 new View.OnAttachStateChangeListener() {
119 @Override
120 public void onViewAttachedToWindow(View v) {
121 }
122
123 @Override
124 public void onViewDetachedFromWindow(View v) {
125 mIsViewVisible = false;
126 }
127 };
128
Beth Thibodeaucb395352019-01-25 15:39:54 -0500129 private MediaController.Callback mMediaCallback = new MediaController.Callback() {
130 @Override
131 public void onSessionDestroyed() {
132 clearTimer();
133 mMediaController.unregisterCallback(this);
Beth Thibodeau4e4c86e2019-08-01 10:57:29 -0400134 if (mView instanceof MediaNotificationView) {
135 ((MediaNotificationView) mView).removeVisibilityListener(mVisibilityListener);
136 mView.removeOnAttachStateChangeListener(mAttachStateListener);
137 }
Beth Thibodeaucb395352019-01-25 15:39:54 -0500138 }
139
140 @Override
Beth Thibodeau2e76ad52019-05-29 11:29:25 -0400141 public void onPlaybackStateChanged(@Nullable PlaybackState state) {
142 if (state == null) {
143 return;
144 }
145
Beth Thibodeaucb395352019-01-25 15:39:54 -0500146 if (state.getState() != PlaybackState.STATE_PLAYING) {
Beth Thibodeau7d5c97a2019-04-10 15:28:07 -0400147 // Update the UI once, in case playback info changed while we were paused
Beth Thibodeau2e76ad52019-05-29 11:29:25 -0400148 updatePlaybackUi(state);
Beth Thibodeaucb395352019-01-25 15:39:54 -0500149 clearTimer();
Beth Thibodeau4b05fbc2019-05-16 12:51:20 -0400150 } else if (mSeekBarTimer == null && mSeekBarView != null
151 && mSeekBarView.getVisibility() != View.GONE) {
Beth Thibodeaucb395352019-01-25 15:39:54 -0500152 startTimer();
153 }
154 }
Beth Thibodeau2e76ad52019-05-29 11:29:25 -0400155
156 @Override
157 public void onMetadataChanged(@Nullable MediaMetadata metadata) {
158 if (mMediaMetadata == null || !mMediaMetadata.equals(metadata)) {
159 mMediaMetadata = metadata;
160 updateDuration();
161 }
162 }
Beth Thibodeaucb395352019-01-25 15:39:54 -0500163 };
164
Selim Cinek7d1c63e2016-04-21 15:26:10 -0700165 protected NotificationMediaTemplateViewWrapper(Context ctx, View view,
166 ExpandableNotificationRow row) {
167 super(ctx, view, row);
Beth Thibodeaucb395352019-01-25 15:39:54 -0500168 mContext = ctx;
Beth Thibodeaueab4dde2019-02-07 11:37:02 -0500169 mMediaManager = Dependency.get(NotificationMediaManager.class);
Beth Thibodeau4b05fbc2019-05-16 12:51:20 -0400170 mMetricsLogger = Dependency.get(MetricsLogger.class);
Selim Cinekdf5bf612016-02-26 09:56:31 -0800171 }
172
Selim Cinek414ad332017-02-24 19:06:12 -0800173 private void resolveViews() {
Selim Cinekdf5bf612016-02-26 09:56:31 -0800174 mActions = mView.findViewById(com.android.internal.R.id.media_actions);
Beth Thibodeau4e4c86e2019-08-01 10:57:29 -0400175 mIsViewVisible = mView.isShown();
Beth Thibodeaucb395352019-01-25 15:39:54 -0500176
Ned Burns00b4b2d2019-10-17 22:09:27 -0400177 final MediaSession.Token token = mRow.getEntry().getSbn().getNotification().extras
Beth Thibodeaucb395352019-01-25 15:39:54 -0500178 .getParcelable(Notification.EXTRA_MEDIA_SESSION);
179
Beth Thibodeau899b5952020-01-07 17:50:07 -0500180 if (Utils.useQsMediaPlayer(mContext) && token != null) {
Beth Thibodeau69b1dfd2019-11-08 15:39:25 -0500181 final int[] compactActions = mRow.getEntry().getSbn().getNotification().extras
182 .getIntArray(Notification.EXTRA_COMPACT_ACTIONS);
Beth Thibodeaufd51bb22019-11-25 13:57:06 -0500183 int tintColor = getNotificationHeader().getOriginalIconColor();
wilsonshihe8321942019-10-18 18:39:46 +0800184 NotificationShadeWindowController ctrl = Dependency.get(
185 NotificationShadeWindowController.class);
186 QuickQSPanel panel = ctrl.getNotificationShadeView().findViewById(
Beth Thibodeau07d20c32019-10-16 13:45:56 -0400187 com.android.systemui.R.id.quick_qs_panel);
Beth Thibodeau899b5952020-01-07 17:50:07 -0500188 StatusBarNotification sbn = mRow.getEntry().getSbn();
189 Notification notif = sbn.getNotification();
Beth Thibodeau07d20c32019-10-16 13:45:56 -0400190 panel.getMediaPlayer().setMediaSession(token,
Beth Thibodeau899b5952020-01-07 17:50:07 -0500191 notif.getSmallIcon(),
Beth Thibodeaufd51bb22019-11-25 13:57:06 -0500192 tintColor,
193 mBackgroundColor,
Beth Thibodeau69b1dfd2019-11-08 15:39:25 -0500194 mActions,
Beth Thibodeau899b5952020-01-07 17:50:07 -0500195 compactActions,
Beth Thibodeaua3d90982020-04-13 23:42:48 -0400196 notif.contentIntent,
197 sbn.getKey());
wilsonshihe8321942019-10-18 18:39:46 +0800198 QSPanel bigPanel = ctrl.getNotificationShadeView().findViewById(
Beth Thibodeau07d20c32019-10-16 13:45:56 -0400199 com.android.systemui.R.id.quick_settings_panel);
200 bigPanel.addMediaSession(token,
Beth Thibodeau899b5952020-01-07 17:50:07 -0500201 notif.getSmallIcon(),
Beth Thibodeaufd51bb22019-11-25 13:57:06 -0500202 tintColor,
203 mBackgroundColor,
Beth Thibodeau07d20c32019-10-16 13:45:56 -0400204 mActions,
Beth Thibodeaua3d90982020-04-13 23:42:48 -0400205 sbn,
206 sbn.getKey());
Beth Thibodeau07d20c32019-10-16 13:45:56 -0400207 }
208
Beth Thibodeaueab4dde2019-02-07 11:37:02 -0500209 boolean showCompactSeekbar = mMediaManager.getShowCompactMediaSeekbar();
210 if (token == null || (COMPACT_MEDIA_TAG.equals(mView.getTag()) && !showCompactSeekbar)) {
Beth Thibodeaucb395352019-01-25 15:39:54 -0500211 if (mSeekBarView != null) {
212 mSeekBarView.setVisibility(View.GONE);
213 }
214 return;
215 }
216
217 // Check for existing media controller and clean up / create as necessary
Beth Thibodeaud1eb0a82019-11-01 15:38:47 -0400218 boolean shouldUpdateListeners = false;
Beth Thibodeaucb395352019-01-25 15:39:54 -0500219 if (mMediaController == null || !mMediaController.getSessionToken().equals(token)) {
220 if (mMediaController != null) {
221 mMediaController.unregisterCallback(mMediaCallback);
222 }
223 mMediaController = new MediaController(mContext, token);
Beth Thibodeaud1eb0a82019-11-01 15:38:47 -0400224 shouldUpdateListeners = true;
Beth Thibodeaucb395352019-01-25 15:39:54 -0500225 }
226
Beth Thibodeau2e76ad52019-05-29 11:29:25 -0400227 mMediaMetadata = mMediaController.getMetadata();
228 if (mMediaMetadata != null) {
229 long duration = mMediaMetadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
Beth Thibodeaucb395352019-01-25 15:39:54 -0500230 if (duration <= 0) {
231 // Don't include the seekbar if this is a livestream
Beth Thibodeau4b05fbc2019-05-16 12:51:20 -0400232 if (mSeekBarView != null && mSeekBarView.getVisibility() != View.GONE) {
Beth Thibodeaucb395352019-01-25 15:39:54 -0500233 mSeekBarView.setVisibility(View.GONE);
Beth Thibodeau4b05fbc2019-05-16 12:51:20 -0400234 mMetricsLogger.write(newLog(MetricsEvent.TYPE_CLOSE));
235 clearTimer();
Beth Thibodeaud1eb0a82019-11-01 15:38:47 -0400236 } else if (mSeekBarView == null && shouldUpdateListeners) {
Beth Thibodeau4b05fbc2019-05-16 12:51:20 -0400237 // Only log if the controller changed, otherwise we would log multiple times for
238 // the same notification when user pauses/resumes
239 mMetricsLogger.write(newLog(MetricsEvent.TYPE_CLOSE));
Beth Thibodeaucb395352019-01-25 15:39:54 -0500240 }
241 return;
Beth Thibodeau2e76ad52019-05-29 11:29:25 -0400242 } else if (mSeekBarView != null && mSeekBarView.getVisibility() == View.GONE) {
Beth Thibodeaucb395352019-01-25 15:39:54 -0500243 // Otherwise, make sure the seekbar is visible
Beth Thibodeau2e76ad52019-05-29 11:29:25 -0400244 mSeekBarView.setVisibility(View.VISIBLE);
245 mMetricsLogger.write(newLog(MetricsEvent.TYPE_OPEN));
246 updateDuration();
247 startTimer();
Beth Thibodeaucb395352019-01-25 15:39:54 -0500248 }
249 }
250
251 // Inflate the seekbar template
252 ViewStub stub = mView.findViewById(R.id.notification_media_seekbar_container);
253 if (stub instanceof ViewStub) {
254 LayoutInflater layoutInflater = LayoutInflater.from(stub.getContext());
255 stub.setLayoutInflater(layoutInflater);
256 stub.setLayoutResource(R.layout.notification_material_media_seekbar);
257 mSeekBarView = stub.inflate();
Beth Thibodeau4b05fbc2019-05-16 12:51:20 -0400258 mMetricsLogger.write(newLog(MetricsEvent.TYPE_OPEN));
Beth Thibodeaucb395352019-01-25 15:39:54 -0500259
260 mSeekBar = mSeekBarView.findViewById(R.id.notification_media_progress_bar);
261 mSeekBar.setOnSeekBarChangeListener(mSeekListener);
262
263 mSeekBarElapsedTime = mSeekBarView.findViewById(R.id.notification_media_elapsed_time);
264 mSeekBarTotalTime = mSeekBarView.findViewById(R.id.notification_media_total_time);
265
Beth Thibodeaud1eb0a82019-11-01 15:38:47 -0400266 shouldUpdateListeners = true;
267 }
268
269 if (shouldUpdateListeners) {
270 if (mView instanceof MediaNotificationView) {
271 MediaNotificationView mediaView = (MediaNotificationView) mView;
272 mediaView.addVisibilityListener(mVisibilityListener);
273 mView.addOnAttachStateChangeListener(mAttachStateListener);
274 }
275
Beth Thibodeaucb395352019-01-25 15:39:54 -0500276 if (mSeekBarTimer == null) {
Beth Thibodeau2e76ad52019-05-29 11:29:25 -0400277 if (mMediaController != null && canSeekMedia(mMediaController.getPlaybackState())) {
Beth Thibodeau4b05fbc2019-05-16 12:51:20 -0400278 // Log initial state, since it will not be updated
279 mMetricsLogger.write(newLog(MetricsEvent.TYPE_DETAIL, 1));
Beth Thibodeaucb395352019-01-25 15:39:54 -0500280 } else {
Beth Thibodeau4b05fbc2019-05-16 12:51:20 -0400281 setScrubberVisible(false);
Beth Thibodeaucb395352019-01-25 15:39:54 -0500282 }
Beth Thibodeau2e76ad52019-05-29 11:29:25 -0400283 updateDuration();
Beth Thibodeaucb395352019-01-25 15:39:54 -0500284 startTimer();
Beth Thibodeaucb395352019-01-25 15:39:54 -0500285 mMediaController.registerCallback(mMediaCallback);
286 }
287 }
288 updateSeekBarTint(mSeekBarView);
289 }
290
291 private void startTimer() {
292 clearTimer();
Beth Thibodeau4e4c86e2019-08-01 10:57:29 -0400293 if (mIsViewVisible) {
294 mSeekBarTimer = new Timer(true /* isDaemon */);
295 mSeekBarTimer.schedule(new TimerTask() {
296 @Override
297 public void run() {
298 mHandler.post(mOnUpdateTimerTick);
299 }
300 }, 0, PROGRESS_UPDATE_INTERVAL);
301 }
Beth Thibodeaucb395352019-01-25 15:39:54 -0500302 }
303
304 private void clearTimer() {
305 if (mSeekBarTimer != null) {
Beth Thibodeaucb395352019-01-25 15:39:54 -0500306 mSeekBarTimer.cancel();
307 mSeekBarTimer.purge();
308 mSeekBarTimer = null;
309 }
310 }
311
Beth Thibodeau4e4c86e2019-08-01 10:57:29 -0400312 @Override
313 public void setRemoved() {
314 clearTimer();
315 if (mMediaController != null) {
316 mMediaController.unregisterCallback(mMediaCallback);
317 }
318 if (mView instanceof MediaNotificationView) {
319 ((MediaNotificationView) mView).removeVisibilityListener(mVisibilityListener);
320 mView.removeOnAttachStateChangeListener(mAttachStateListener);
321 }
322 }
323
Beth Thibodeau2e76ad52019-05-29 11:29:25 -0400324 private boolean canSeekMedia(@Nullable PlaybackState state) {
325 if (state == null) {
Beth Thibodeaucb395352019-01-25 15:39:54 -0500326 return false;
327 }
328
Beth Thibodeau2e76ad52019-05-29 11:29:25 -0400329 long actions = state.getActions();
Beth Thibodeau1c081642019-05-06 09:43:26 -0400330 return ((actions & PlaybackState.ACTION_SEEK_TO) != 0);
Beth Thibodeaucb395352019-01-25 15:39:54 -0500331 }
332
Beth Thibodeau4b05fbc2019-05-16 12:51:20 -0400333 private void setScrubberVisible(boolean isVisible) {
334 if (mSeekBar == null || mSeekBar.isEnabled() == isVisible) {
335 return;
336 }
337
338 mSeekBar.getThumb().setAlpha(isVisible ? 255 : 0);
339 mSeekBar.setEnabled(isVisible);
340 mMetricsLogger.write(newLog(MetricsEvent.TYPE_DETAIL, isVisible ? 1 : 0));
341 }
342
Beth Thibodeau2e76ad52019-05-29 11:29:25 -0400343 private void updateDuration() {
344 if (mMediaMetadata != null && mSeekBar != null) {
345 long duration = mMediaMetadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
346 if (mDuration != duration) {
347 mDuration = duration;
348 mSeekBar.setMax((int) mDuration);
349 mSeekBarTotalTime.setText(millisecondsToTimeString(duration));
350 }
351 }
352 }
353
354 protected final Runnable mOnUpdateTimerTick = new Runnable() {
Beth Thibodeaucb395352019-01-25 15:39:54 -0500355 @Override
356 public void run() {
Beth Thibodeau4e937fa2019-04-24 15:15:09 -0400357 if (mMediaController != null && mSeekBar != null) {
Beth Thibodeau4e937fa2019-04-24 15:15:09 -0400358 PlaybackState playbackState = mMediaController.getPlaybackState();
Beth Thibodeau2e76ad52019-05-29 11:29:25 -0400359 if (playbackState != null) {
360 updatePlaybackUi(playbackState);
Beth Thibodeau4e937fa2019-04-24 15:15:09 -0400361 } else {
Beth Thibodeau4e937fa2019-04-24 15:15:09 -0400362 clearTimer();
Beth Thibodeaucb395352019-01-25 15:39:54 -0500363 }
Beth Thibodeaucb395352019-01-25 15:39:54 -0500364 } else {
Beth Thibodeaucb395352019-01-25 15:39:54 -0500365 clearTimer();
366 }
367 }
368 };
369
Beth Thibodeau2e76ad52019-05-29 11:29:25 -0400370 private void updatePlaybackUi(PlaybackState state) {
Beth Thibodeau4e4c86e2019-08-01 10:57:29 -0400371 if (mSeekBar == null || mSeekBarElapsedTime == null) {
372 return;
373 }
374
Beth Thibodeau2e76ad52019-05-29 11:29:25 -0400375 long position = state.getPosition();
376 mSeekBar.setProgress((int) position);
377
378 mSeekBarElapsedTime.setText(millisecondsToTimeString(position));
379
380 // Update scrubber in case available actions have changed
381 setScrubberVisible(canSeekMedia(state));
382 }
383
Beth Thibodeaucb395352019-01-25 15:39:54 -0500384 private String millisecondsToTimeString(long milliseconds) {
385 long seconds = milliseconds / 1000;
386 String text = DateUtils.formatElapsedTime(seconds);
387 return text;
Selim Cinekdf5bf612016-02-26 09:56:31 -0800388 }
389
390 @Override
Selim Cinek131f1a42017-06-05 17:50:19 -0700391 public void onContentUpdated(ExpandableNotificationRow row) {
Selim Cinekdf5bf612016-02-26 09:56:31 -0800392 // Reinspect the notification. Before the super call, because the super call also updates
393 // the transformation types and we need to have our values set by then.
Selim Cinek414ad332017-02-24 19:06:12 -0800394 resolveViews();
Selim Cinek131f1a42017-06-05 17:50:19 -0700395 super.onContentUpdated(row);
Selim Cinekdf5bf612016-02-26 09:56:31 -0800396 }
397
Beth Thibodeaucb395352019-01-25 15:39:54 -0500398 private void updateSeekBarTint(View seekBarContainer) {
399 if (seekBarContainer == null) {
400 return;
401 }
402
403 if (this.getNotificationHeader() == null) {
404 return;
405 }
406
407 int tintColor = getNotificationHeader().getOriginalIconColor();
408 mSeekBarElapsedTime.setTextColor(tintColor);
409 mSeekBarTotalTime.setTextColor(tintColor);
Beth Thibodeau55004172019-05-30 17:52:08 -0400410 mSeekBarTotalTime.setShadowLayer(1.5f, 1.5f, 1.5f, mBackgroundColor);
Beth Thibodeaucb395352019-01-25 15:39:54 -0500411
412 ColorStateList tintList = ColorStateList.valueOf(tintColor);
413 mSeekBar.setThumbTintList(tintList);
414 tintList = tintList.withAlpha(192); // 75%
415 mSeekBar.setProgressTintList(tintList);
416 tintList = tintList.withAlpha(128); // 50%
417 mSeekBar.setProgressBackgroundTintList(tintList);
418 }
419
Selim Cinekdf5bf612016-02-26 09:56:31 -0800420 @Override
421 protected void updateTransformedTypes() {
422 // This also clears the existing types
423 super.updateTransformedTypes();
424 if (mActions != null) {
Selim Cinekf88c6292016-04-26 16:58:21 -0700425 mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_ACTIONS,
Selim Cinekdf5bf612016-02-26 09:56:31 -0800426 mActions);
427 }
428 }
Selim Cinek63edaf22017-04-24 22:18:48 -0700429
430 @Override
431 public boolean isDimmable() {
Selim Cinek74c2bad2017-11-27 15:09:36 +0100432 return getCustomBackgroundColor() == 0;
Selim Cinek63edaf22017-04-24 22:18:48 -0700433 }
Selim Cinek515b2032017-11-15 10:20:19 -0800434
435 @Override
Selim Cinek86bfcee2018-01-17 11:00:47 -0800436 public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
Selim Cinek515b2032017-11-15 10:20:19 -0800437 return true;
438 }
Beth Thibodeau4b05fbc2019-05-16 12:51:20 -0400439
440 /**
441 * Returns an initialized LogMaker for logging changes to the seekbar
442 * @return new LogMaker
443 */
444 private LogMaker newLog(int event) {
Ned Burns00b4b2d2019-10-17 22:09:27 -0400445 String packageName = mRow.getEntry().getSbn().getPackageName();
Beth Thibodeau4b05fbc2019-05-16 12:51:20 -0400446
447 return new LogMaker(MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR)
448 .setType(event)
449 .setPackageName(packageName);
450 }
451
452 /**
453 * Returns an initialized LogMaker for logging changes with subtypes
454 * @return new LogMaker
455 */
456 private LogMaker newLog(int event, int subtype) {
Ned Burns00b4b2d2019-10-17 22:09:27 -0400457 String packageName = mRow.getEntry().getSbn().getPackageName();
Beth Thibodeau4b05fbc2019-05-16 12:51:20 -0400458 return new LogMaker(MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR)
459 .setType(event)
460 .setSubtype(subtype)
461 .setPackageName(packageName);
462 }
Selim Cinekdf5bf612016-02-26 09:56:31 -0800463}