OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.media.ui; | 5 package org.chromium.chrome.browser.media.ui; |
6 | 6 |
7 import android.app.Notification; | 7 import android.app.Notification; |
8 import android.app.PendingIntent; | 8 import android.app.PendingIntent; |
9 import android.app.Service; | 9 import android.app.Service; |
10 import android.content.BroadcastReceiver; | 10 import android.content.BroadcastReceiver; |
(...skipping 18 matching lines...) Expand all Loading... | |
29 import android.support.v7.app.NotificationCompat; | 29 import android.support.v7.app.NotificationCompat; |
30 import android.support.v7.media.MediaRouter; | 30 import android.support.v7.media.MediaRouter; |
31 import android.text.TextUtils; | 31 import android.text.TextUtils; |
32 import android.util.SparseArray; | 32 import android.util.SparseArray; |
33 import android.view.KeyEvent; | 33 import android.view.KeyEvent; |
34 | 34 |
35 import org.chromium.base.SysUtils; | 35 import org.chromium.base.SysUtils; |
36 import org.chromium.base.VisibleForTesting; | 36 import org.chromium.base.VisibleForTesting; |
37 import org.chromium.blink.mojom.MediaSessionAction; | 37 import org.chromium.blink.mojom.MediaSessionAction; |
38 import org.chromium.chrome.R; | 38 import org.chromium.chrome.R; |
39 import org.chromium.chrome.browser.ChromeApplication; | |
40 import org.chromium.chrome.browser.notifications.ChromeNotificationBuilder; | |
39 import org.chromium.chrome.browser.notifications.NotificationConstants; | 41 import org.chromium.chrome.browser.notifications.NotificationConstants; |
40 import org.chromium.content_public.common.MediaMetadata; | 42 import org.chromium.content_public.common.MediaMetadata; |
41 | 43 |
42 import java.util.ArrayList; | 44 import java.util.ArrayList; |
43 import java.util.HashSet; | 45 import java.util.HashSet; |
44 import java.util.List; | 46 import java.util.List; |
45 import java.util.Set; | 47 import java.util.Set; |
46 | 48 |
47 import javax.annotation.Nullable; | 49 import javax.annotation.Nullable; |
48 | 50 |
(...skipping 28 matching lines...) Expand all Loading... | |
77 // Maps the notification ids to their corresponding notification managers. | 79 // Maps the notification ids to their corresponding notification managers. |
78 private static SparseArray<MediaNotificationManager> sManagers; | 80 private static SparseArray<MediaNotificationManager> sManagers; |
79 | 81 |
80 private final Context mContext; | 82 private final Context mContext; |
81 | 83 |
82 // ListenerService running for the notification. Only non-null when showing. | 84 // ListenerService running for the notification. Only non-null when showing. |
83 private ListenerService mService; | 85 private ListenerService mService; |
84 | 86 |
85 private SparseArray<MediaButtonInfo> mActionToButtonInfo; | 87 private SparseArray<MediaButtonInfo> mActionToButtonInfo; |
86 | 88 |
87 private NotificationCompat.Builder mNotificationBuilder; | 89 private ChromeNotificationBuilder mNotificationBuilder; |
88 | 90 |
89 private Bitmap mDefaultNotificationLargeIcon; | 91 private Bitmap mDefaultNotificationLargeIcon; |
90 | 92 |
91 // |mMediaNotificationInfo| should be not null if and only if the notificati on is showing. | 93 // |mMediaNotificationInfo| should be not null if and only if the notificati on is showing. |
92 private MediaNotificationInfo mMediaNotificationInfo; | 94 private MediaNotificationInfo mMediaNotificationInfo; |
93 | 95 |
94 private MediaSessionCompat mMediaSession; | 96 private MediaSessionCompat mMediaSession; |
95 | 97 |
96 private final MediaSessionCompat.Callback mMediaSessionCallback = | 98 private final MediaSessionCompat.Callback mMediaSessionCallback = |
97 new MediaSessionCompat.Callback() { | 99 new MediaSessionCompat.Callback() { |
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
531 return sManagers.get(notificationId); | 533 return sManagers.get(notificationId); |
532 } | 534 } |
533 | 535 |
534 @VisibleForTesting | 536 @VisibleForTesting |
535 static boolean hasManagerForTesting(int notificationId) { | 537 static boolean hasManagerForTesting(int notificationId) { |
536 return getManager(notificationId) != null; | 538 return getManager(notificationId) != null; |
537 } | 539 } |
538 | 540 |
539 @VisibleForTesting | 541 @VisibleForTesting |
540 @Nullable | 542 @Nullable |
541 static NotificationCompat.Builder getNotificationBuilderForTesting( | 543 static ChromeNotificationBuilder getNotificationBuilderForTesting(int notifi cationId) { |
542 int notificationId) { | |
543 MediaNotificationManager manager = getManager(notificationId); | 544 MediaNotificationManager manager = getManager(notificationId); |
544 if (manager == null) return null; | 545 if (manager == null) return null; |
545 | 546 |
546 return manager.mNotificationBuilder; | 547 return manager.mNotificationBuilder; |
547 } | 548 } |
548 | 549 |
549 @VisibleForTesting | 550 @VisibleForTesting |
550 @Nullable | 551 @Nullable |
551 static MediaNotificationInfo getMediaNotificationInfoForTesting( | 552 static MediaNotificationInfo getMediaNotificationInfoForTesting( |
552 int notificationId) { | 553 int notificationId) { |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
709 return metadataBuilder.build(); | 710 return metadataBuilder.build(); |
710 } | 711 } |
711 | 712 |
712 private void updateNotification() { | 713 private void updateNotification() { |
713 if (mService == null) return; | 714 if (mService == null) return; |
714 | 715 |
715 if (mMediaNotificationInfo == null) return; | 716 if (mMediaNotificationInfo == null) return; |
716 | 717 |
717 updateMediaSession(); | 718 updateMediaSession(); |
718 | 719 |
719 mNotificationBuilder = new NotificationCompat.Builder(mContext); | 720 mNotificationBuilder = |
721 ((ChromeApplication) mContext) | |
nyquist
2017/02/28 07:33:17
I think you need to do mContext.getApplicationCont
mlamouri (slow - plz ping)
2017/02/28 15:23:11
+1. The context you are getting here is probably n
awdf
2017/02/28 18:09:05
Done.
| |
722 .createChromeNotificationBuilder(true, | |
723 NotificationConstants.CATEGORY_ID_GENERAL, | |
mlamouri (slow - plz ping)
2017/02/28 15:23:11
Should this be media?
awdf
2017/02/28 18:09:05
As discussed, we're going with GENERAL for now.
| |
724 mContext.getString(R.string.notification_categor y_general)); | |
720 setMediaStyleLayoutForNotificationBuilder(mNotificationBuilder); | 725 setMediaStyleLayoutForNotificationBuilder(mNotificationBuilder); |
721 | 726 |
722 mNotificationBuilder.setSmallIcon(mMediaNotificationInfo.notificationSma llIcon); | 727 mNotificationBuilder.setSmallIcon(mMediaNotificationInfo.notificationSma llIcon); |
723 mNotificationBuilder.setAutoCancel(false); | 728 mNotificationBuilder.setAutoCancel(false); |
724 mNotificationBuilder.setLocalOnly(true); | 729 mNotificationBuilder.setLocalOnly(true); |
725 mNotificationBuilder.setGroup(getNotificationGroupName()); | 730 mNotificationBuilder.setGroup(getNotificationGroupName()); |
726 mNotificationBuilder.setGroupSummary(true); | 731 mNotificationBuilder.setGroupSummary(true); |
727 | 732 |
728 if (mMediaNotificationInfo.supportsSwipeAway()) { | 733 if (mMediaNotificationInfo.supportsSwipeAway()) { |
729 mNotificationBuilder.setOngoing(!mMediaNotificationInfo.isPaused); | 734 mNotificationBuilder.setOngoing(!mMediaNotificationInfo.isPaused); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
841 } | 846 } |
842 | 847 |
843 private void activateAndroidMediaSession(int tabId) { | 848 private void activateAndroidMediaSession(int tabId) { |
844 if (mMediaNotificationInfo == null) return; | 849 if (mMediaNotificationInfo == null) return; |
845 if (mMediaNotificationInfo.tabId != tabId) return; | 850 if (mMediaNotificationInfo.tabId != tabId) return; |
846 if (!mMediaNotificationInfo.supportsPlayPause() || mMediaNotificationInf o.isPaused) return; | 851 if (!mMediaNotificationInfo.supportsPlayPause() || mMediaNotificationInf o.isPaused) return; |
847 if (mMediaSession == null) return; | 852 if (mMediaSession == null) return; |
848 mMediaSession.setActive(true); | 853 mMediaSession.setActive(true); |
849 } | 854 } |
850 | 855 |
851 private void setMediaStyleLayoutForNotificationBuilder(NotificationCompat.Bu ilder builder) { | 856 private void setMediaStyleLayoutForNotificationBuilder(ChromeNotificationBui lder builder) { |
852 setMediaStyleNotificationText(builder); | 857 setMediaStyleNotificationText(builder); |
853 if (!mMediaNotificationInfo.supportsPlayPause()) { | 858 if (!mMediaNotificationInfo.supportsPlayPause()) { |
854 builder.setLargeIcon(null); | 859 builder.setLargeIcon(null); |
855 } else if (mMediaNotificationInfo.notificationLargeIcon != null) { | 860 } else if (mMediaNotificationInfo.notificationLargeIcon != null) { |
856 builder.setLargeIcon(mMediaNotificationInfo.notificationLargeIcon); | 861 builder.setLargeIcon(mMediaNotificationInfo.notificationLargeIcon); |
857 } else if (!isRunningN()) { | 862 } else if (!isRunningN()) { |
858 if (mDefaultNotificationLargeIcon == null) { | 863 if (mDefaultNotificationLargeIcon == null) { |
859 int resourceId = (mMediaNotificationInfo.defaultNotificationLarg eIcon != 0) | 864 int resourceId = (mMediaNotificationInfo.defaultNotificationLarg eIcon != 0) |
860 ? mMediaNotificationInfo.defaultNotificationLargeIcon | 865 ? mMediaNotificationInfo.defaultNotificationLargeIcon |
861 : R.drawable.audio_playing_square; | 866 : R.drawable.audio_playing_square; |
862 mDefaultNotificationLargeIcon = downscaleIconToIdealSize( | 867 mDefaultNotificationLargeIcon = downscaleIconToIdealSize( |
863 BitmapFactory.decodeResource(mContext.getResources(), resour ceId)); | 868 BitmapFactory.decodeResource(mContext.getResources(), resour ceId)); |
864 } | 869 } |
865 builder.setLargeIcon(mDefaultNotificationLargeIcon); | 870 builder.setLargeIcon(mDefaultNotificationLargeIcon); |
866 } | 871 } |
867 // TODO(zqzhang): It's weird that setShowWhen() don't work on K. Calling setWhen() to force | 872 // TODO(zqzhang): It's weird that setShowWhen() don't work on K. Calling setWhen() to force |
868 // removing the time. | 873 // removing the time. |
869 builder.setShowWhen(false).setWhen(0); | 874 builder.setShowWhen(false).setWhen(0); |
870 | 875 |
871 addNotificationButtons(builder); | 876 addNotificationButtons(builder); |
872 } | 877 } |
873 | 878 |
874 private void addNotificationButtons(NotificationCompat.Builder builder) { | 879 private void addNotificationButtons(ChromeNotificationBuilder builder) { |
875 Set<Integer> actions = new HashSet<>(); | 880 Set<Integer> actions = new HashSet<>(); |
876 | 881 |
877 // TODO(zqzhang): handle other actions when play/pause is not supported? See | 882 // TODO(zqzhang): handle other actions when play/pause is not supported? See |
878 // https://crbug.com/667500 | 883 // https://crbug.com/667500 |
879 if (mMediaNotificationInfo.supportsPlayPause()) { | 884 if (mMediaNotificationInfo.supportsPlayPause()) { |
880 actions.addAll(mMediaNotificationInfo.mediaSessionActions); | 885 actions.addAll(mMediaNotificationInfo.mediaSessionActions); |
881 if (mMediaNotificationInfo.isPaused) { | 886 if (mMediaNotificationInfo.isPaused) { |
882 actions.remove(MediaSessionAction.PAUSE); | 887 actions.remove(MediaSessionAction.PAUSE); |
883 actions.add(MediaSessionAction.PLAY); | 888 actions.add(MediaSessionAction.PLAY); |
884 } else { | 889 } else { |
(...skipping 10 matching lines...) Expand all Loading... | |
895 | 900 |
896 for (int action : bigViewActions) { | 901 for (int action : bigViewActions) { |
897 MediaButtonInfo buttonInfo = mActionToButtonInfo.get(action); | 902 MediaButtonInfo buttonInfo = mActionToButtonInfo.get(action); |
898 builder.addAction(buttonInfo.iconResId, | 903 builder.addAction(buttonInfo.iconResId, |
899 mContext.getResources().getString(buttonInfo.descriptionResI d), | 904 mContext.getResources().getString(buttonInfo.descriptionResI d), |
900 createPendingIntent(buttonInfo.intentString)); | 905 createPendingIntent(buttonInfo.intentString)); |
901 } | 906 } |
902 | 907 |
903 // Only apply MediaStyle when NotificationInfo supports play/pause. | 908 // Only apply MediaStyle when NotificationInfo supports play/pause. |
904 if (mMediaNotificationInfo.supportsPlayPause()) { | 909 if (mMediaNotificationInfo.supportsPlayPause()) { |
905 NotificationCompat.MediaStyle style = new NotificationCompat.MediaSt yle(); | 910 builder.setMediaStyle(mMediaSession, computeCompactViewActionIndices (bigViewActions), |
906 style.setMediaSession(mMediaSession.getSessionToken()); | 911 createPendingIntent(ListenerService.ACTION_CANCEL), true); |
907 | |
908 int[] compactViewActionIndices = computeCompactViewActionIndices(big ViewActions); | |
909 | |
910 style.setShowActionsInCompactView(compactViewActionIndices); | |
911 style.setCancelButtonIntent(createPendingIntent(ListenerService.ACTI ON_CANCEL)); | |
912 style.setShowCancelButton(true); | |
913 builder.setStyle(style); | |
914 } | 912 } |
915 } | 913 } |
916 | 914 |
917 private Bitmap drawableToBitmap(Drawable drawable) { | 915 private Bitmap drawableToBitmap(Drawable drawable) { |
918 if (!(drawable instanceof BitmapDrawable)) return null; | 916 if (!(drawable instanceof BitmapDrawable)) return null; |
919 | 917 |
920 BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; | 918 BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; |
921 return bitmapDrawable.getBitmap(); | 919 return bitmapDrawable.getBitmap(); |
922 } | 920 } |
923 | 921 |
924 private void setMediaStyleNotificationText(NotificationCompat.Builder builde r) { | 922 private void setMediaStyleNotificationText(ChromeNotificationBuilder builder ) { |
925 builder.setContentTitle(mMediaNotificationInfo.metadata.getTitle()); | 923 builder.setContentTitle(mMediaNotificationInfo.metadata.getTitle()); |
926 String artistAndAlbumText = getArtistAndAlbumText(mMediaNotificationInfo .metadata); | 924 String artistAndAlbumText = getArtistAndAlbumText(mMediaNotificationInfo .metadata); |
927 if (isRunningN() || !artistAndAlbumText.isEmpty()) { | 925 if (isRunningN() || !artistAndAlbumText.isEmpty()) { |
928 builder.setContentText(artistAndAlbumText); | 926 builder.setContentText(artistAndAlbumText); |
929 builder.setSubText(mMediaNotificationInfo.origin); | 927 builder.setSubText(mMediaNotificationInfo.origin); |
930 } else { | 928 } else { |
931 // Leaving ContentText empty looks bad, so move origin up to the Con tentText. | 929 // Leaving ContentText empty looks bad, so move origin up to the Con tentText. |
932 builder.setContentText(mMediaNotificationInfo.origin); | 930 builder.setContentText(mMediaNotificationInfo.origin); |
933 } | 931 } |
934 } | 932 } |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1068 | 1066 |
1069 return actionsArray; | 1067 return actionsArray; |
1070 } | 1068 } |
1071 | 1069 |
1072 static int[] convertIntegerListToIntArray(List<Integer> intList) { | 1070 static int[] convertIntegerListToIntArray(List<Integer> intList) { |
1073 int[] intArray = new int[intList.size()]; | 1071 int[] intArray = new int[intList.size()]; |
1074 for (int i = 0; i < intList.size(); ++i) intArray[i] = i; | 1072 for (int i = 0; i < intList.size(); ++i) intArray[i] = i; |
1075 return intArray; | 1073 return intArray; |
1076 } | 1074 } |
1077 } | 1075 } |
OLD | NEW |