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.systemui.cts.audiorecorder.base;
18 
19 
20 import android.app.Notification;
21 import android.app.NotificationChannel;
22 import android.app.NotificationManager;
23 import android.app.Service;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.os.Handler;
27 import android.os.IBinder;
28 import android.os.Looper;
29 
30 public abstract class BaseAudioRecorderService extends Service {
31     private static final String ACTION_START =
32             "android.systemui.cts.audiorecorder.ACTION_START";
33     private static final String ACTION_STOP =
34             "android.systemui.cts.audiorecorder.ACTION_STOP";
35     private static final String ACTION_THROW =
36             "android.systemui.cts.audiorecorder.ACTION_THROW";
37 
38     private static final String NOTIFICATION_CHANNEL_ID = "all";
39     private static final String NOTIFICATION_CHANNEL_NAME = "All Notifications";
40     private static final int NOTIFICATION_ID = 1;
41     private static final String NOTIFICATION_TITLE = "Audio Record Service";
42     private static final String NOTIFICATION_TEXT = "Recording...";
43 
44     private Handler mHandler;
45     private final Runnable mCrashRunnable = () -> {
46         throw new RuntimeException("Commanded to throw!");
47     };
48 
49     @Override
onCreate()50     public void onCreate() {
51         super.onCreate();
52         mHandler = new Handler(Looper.getMainLooper());
53     }
54 
55     @Override
onStartCommand(Intent intent, int flags, int startId)56     public int onStartCommand(Intent intent, int flags, int startId) {
57         startForeground(NOTIFICATION_ID, buildNotification());
58 
59         final String action = intent.getAction();
60         if (ACTION_START.equals(action) && !isRecording()) {
61             startRecording();
62         } else if (ACTION_STOP.equals(action) && isRecording()) {
63             stopRecording();
64         } else if (ACTION_THROW.equals(action)) {
65             // If the service crashes in onStartCommand() the system will try to re-start it. We do
66             // not want that. So we post "crash" commands.
67             mHandler.post(mCrashRunnable);
68         }
69 
70         if (!isRecording()) {
71             stopForeground(true);
72             stopSelf();
73         }
74 
75         return START_NOT_STICKY;
76     }
77 
startRecording()78     protected abstract void startRecording();
79 
stopRecording()80     protected abstract void stopRecording();
81 
isRecording()82     protected abstract boolean isRecording();
83 
84     @Override
onDestroy()85     public void onDestroy() {
86         if (isRecording()) {
87             stopRecording();
88         }
89     }
90 
91     @Override
onBind(Intent intent)92     public IBinder onBind(Intent intent) {
93         return null;
94     }
95 
buildNotification()96     private Notification buildNotification() {
97         // Make sure the channel exists
98         createChannel();
99 
100         return new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
101                 .setContentTitle(NOTIFICATION_TITLE)
102                 .setContentText(NOTIFICATION_TEXT)
103                 .setSmallIcon(R.drawable.ic_fg)
104                 .build();
105     }
106 
createChannel()107     private void createChannel() {
108         final NotificationChannel channel =
109                 new NotificationChannel(
110                         NOTIFICATION_CHANNEL_ID,
111                         NOTIFICATION_CHANNEL_NAME,
112                         NotificationManager.IMPORTANCE_NONE);
113         final NotificationManager manager =
114                 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
115         manager.createNotificationChannel(channel);
116     }
117 }
118