• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 
17 package android.app.stubs;
18 
19 import android.app.ForegroundServiceStartNotAllowedException;
20 import android.app.Notification;
21 import android.app.NotificationChannel;
22 import android.app.NotificationManager;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.content.pm.ServiceInfo;
26 import android.media.session.MediaSession;
27 import android.media.session.PlaybackState;
28 import android.util.Log;
29 
30 /**
31  * Foreground Service with media type.
32  */
33 public class LocalForegroundServiceMedia extends LocalForegroundService {
34 
35     private static final String TAG = "LocalForegroundServiceMedia";
36     private static final String NOTIFICATION_CHANNEL_ID = "cts/" + TAG;
37     public static final String EXTRA_FOREGROUND_SERVICE_TYPE = "ForegroundService.type";
38     public static final int COMMAND_START_FOREGROUND_WITH_TYPE = 1;
39     public static final int COMMAND_PLAY_MEDIA = 100;
40     public static final int COMMAND_POST_MEDIA_NOTIFICATION = 101;
41     public static final int COMMAND_DEACTIVATE_MEDIA_SESSION = 102;
42     public static final int COMMAND_RELEASE_MEDIA_SESSION = 103;
43     public static final int COMMAND_STOP_MEDIA = 104;
44     public static String ACTION_START_FGSM_RESULT =
45             "android.app.stubs.LocalForegroundServiceMedia.RESULT";
46     public static String FGSM_NOTIFICATION_ID =
47             "android.app.stubs.LocalForegroundServiceMedia.NOTIFICATION_ID";
48     private int mNotificationId = 1000;
49 
50     private MediaSession mMediaSession = null;
51 
52     /** Returns the channel id for this service */
getNotificationChannelId()53     public static String getNotificationChannelId() {
54         return NOTIFICATION_CHANNEL_ID;
55     }
56 
57     private static long sAllPlayStateActions =
58             PlaybackState.ACTION_PLAY
59                     | PlaybackState.ACTION_PAUSE
60                     | PlaybackState.ACTION_PLAY_PAUSE
61                     | PlaybackState.ACTION_STOP
62                     | PlaybackState.ACTION_SKIP_TO_NEXT
63                     | PlaybackState.ACTION_SKIP_TO_PREVIOUS
64                     | PlaybackState.ACTION_FAST_FORWARD
65                     | PlaybackState.ACTION_REWIND;
66 
setPlaybackState(int state, MediaSession mediaSession)67     private void setPlaybackState(int state, MediaSession mediaSession) {
68         PlaybackState playbackState =
69                 new PlaybackState.Builder()
70                         .setActions(sAllPlayStateActions)
71                         .setState(state, 0L, 0.0f)
72                         .build();
73         mediaSession.setPlaybackState(playbackState);
74     }
75 
76     @Override
onCreate()77     public void onCreate() {
78         super.onCreate();
79         mMediaSession = new MediaSession(this, TAG);
80         mMediaSession.setCallback(
81                 new MediaSession.Callback() {
82                     @Override
83                     public void onPlay() {
84                         Log.d(TAG, "received onPlay");
85                         super.onPlay();
86                         setPlaybackState(PlaybackState.STATE_PLAYING, mMediaSession);
87                     }
88 
89                     @Override
90                     public void onPause() {
91                         Log.d(TAG, "received onPause");
92                         super.onPause();
93                         setPlaybackState(PlaybackState.STATE_PAUSED, mMediaSession);
94                     }
95 
96                     @Override
97                     public void onStop() {
98                         Log.d(TAG, "received onStop");
99                         super.onStop();
100                         setPlaybackState(PlaybackState.STATE_PAUSED, mMediaSession);
101                     }
102                 });
103         mMediaSession.setActive(true);
104         Log.d(
105                 getTag(),
106                 "service created: "
107                         + this
108                         + " in "
109                         + android.os.Process.myPid()
110                         + "with media session: "
111                         + mMediaSession);
112     }
113 
114     @Override
onDestroy()115     public void onDestroy() {
116         mMediaSession.release();
117         mMediaSession = null;
118         super.onDestroy();
119     }
120 
121     @Override
onStartCommand(Intent intent, int flags, int startId)122     public int onStartCommand(Intent intent, int flags, int startId) {
123         String notificationChannelId = getNotificationChannelId();
124         NotificationManager notificationManager = getSystemService(NotificationManager.class);
125         notificationManager.createNotificationChannel(new NotificationChannel(
126                 notificationChannelId, notificationChannelId,
127                 NotificationManager.IMPORTANCE_DEFAULT));
128 
129         Context context = getApplicationContext();
130         int command = intent.getIntExtra(EXTRA_COMMAND, -1);
131         Intent reply = new Intent(ACTION_START_FGSM_RESULT).setFlags(
132                 Intent.FLAG_RECEIVER_FOREGROUND);
133         switch (command) {
134             case COMMAND_START_FOREGROUND_WITH_TYPE:
135                 final int type = intent.getIntExtra(EXTRA_FOREGROUND_SERVICE_TYPE,
136                         ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST);
137                 mNotificationId++;
138                 final Notification notification =
139                         new Notification.Builder(context, NOTIFICATION_CHANNEL_ID)
140                                 .setContentTitle(getNotificationTitle(mNotificationId))
141                                 .setSmallIcon(R.drawable.black)
142                                 .setStyle(
143                                         new Notification.MediaStyle()
144                                                 .setMediaSession(mMediaSession.getSessionToken()))
145                                 .build();
146                 try {
147                     startForeground(mNotificationId, notification, type);
148                     reply.putExtra(FGSM_NOTIFICATION_ID, mNotificationId);
149                 } catch (ForegroundServiceStartNotAllowedException e) {
150                     Log.d(TAG, "startForeground gets an "
151                             + " ForegroundServiceStartNotAllowedException", e);
152                 }
153                 break;
154             case COMMAND_STOP_FOREGROUND_REMOVE_NOTIFICATION:
155                 Log.d(TAG, "Stopping foreground removing notification");
156                 stopForeground(true);
157                 break;
158             case COMMAND_START_NO_FOREGROUND:
159                 Log.d(TAG, "Starting without calling startForeground()");
160                 break;
161             case COMMAND_POST_MEDIA_NOTIFICATION:
162                 Log.d(TAG, "Posting media style notification");
163                 final Notification notification1 =
164                         new Notification.Builder(context, NOTIFICATION_CHANNEL_ID)
165                                 .setContentTitle(getNotificationTitle(mNotificationId))
166                                 .setSmallIcon(R.drawable.black)
167                                 .setStyle(
168                                         new Notification.MediaStyle()
169                                                 .setMediaSession(mMediaSession.getSessionToken()))
170                                 .build();
171                 notificationManager.notify(mNotificationId++, notification1);
172                 break;
173 
174             case COMMAND_PLAY_MEDIA:
175                 Log.d(TAG, "Setting media session state to playing");
176                 setPlaybackState(PlaybackState.STATE_PLAYING, mMediaSession);
177                 break;
178             case COMMAND_STOP_MEDIA:
179                 Log.d(TAG, "Setting media session state to stopped");
180                 setPlaybackState(PlaybackState.STATE_STOPPED, mMediaSession);
181                 break;
182             case COMMAND_DEACTIVATE_MEDIA_SESSION:
183                 Log.d(TAG, "Deactivating media session");
184                 mMediaSession.setActive(false);
185                 break;
186             case COMMAND_RELEASE_MEDIA_SESSION:
187                 Log.d(TAG, "Release media session");
188                 mMediaSession.release();
189                 break;
190             default:
191                 Log.e(TAG, "Unknown command: " + command);
192         }
193         sendBroadcast(reply);
194         return START_NOT_STICKY;
195     }
196 }
197