1 /*
2  * Copyright (C) 2020 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 com.android.emergency.action.sensoryfeedback;
18 
19 import android.content.Context;
20 import android.media.AudioAttributes;
21 import android.media.AudioManager;
22 import android.media.MediaPlayer;
23 import android.provider.Settings;
24 import android.util.Log;
25 
26 import com.android.emergency.action.EmergencyActionUtils;
27 import com.android.emergency.action.R;
28 
29 
30 public class EmergencyActionAlarmHelper {
31     private static final String TAG = "AlarmSoundManager";
32     private static final int USER_SET_ALARM_VOLUME_UNKNOWN = -1;
33     private final Context mContext;
34 
35     private MediaPlayer mMediaPlayer;
36     private AudioManager mAudioManager;
37     private int mUserSetAlarmVolume;
38     private boolean mResetAlarmVolumeNeeded;
39 
EmergencyActionAlarmHelper(Context context)40     public EmergencyActionAlarmHelper(Context context) {
41         this(context, USER_SET_ALARM_VOLUME_UNKNOWN);
42     }
43 
getUserSetAlarmVolume()44     public int getUserSetAlarmVolume() {
45         return mUserSetAlarmVolume;
46     }
47 
EmergencyActionAlarmHelper(Context context, int userSetAlarmVolume)48     public EmergencyActionAlarmHelper(Context context, int userSetAlarmVolume) {
49         mContext = context;
50         mAudioManager = context.getSystemService(AudioManager.class);
51         mUserSetAlarmVolume = userSetAlarmVolume;
52     }
53 
playWarningSound()54     public void playWarningSound() {
55         if (!isPlayWarningSoundEnabled()) {
56             return;
57         }
58 
59         if (mMediaPlayer == null) {
60             mMediaPlayer = MediaPlayer.create(
61                     mContext,
62                     R.raw.alarm,
63                     new AudioAttributes.Builder()
64                             .setUsage(AudioAttributes.USAGE_ALARM)
65                             .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
66                             .build(),
67                     /* audioSessionId= */ 0);
68         }
69 
70         mMediaPlayer.setOnCompletionListener(mp -> mp.release());
71         mMediaPlayer.setOnErrorListener(
72                 (MediaPlayer mp, int what, int extra) -> {
73                     Log.w(TAG, "MediaPlayer playback failed with error code: " + what
74                             + ", and extra code: " + extra);
75                     mp.release();
76                     return false;
77                 });
78 
79         setAlarmVolumeToFull();
80         mMediaPlayer.start();
81     }
82 
stopWarningSound()83     public void stopWarningSound() {
84         if (mMediaPlayer != null) {
85             try {
86                 mMediaPlayer.stop();
87                 mMediaPlayer.release();
88             } catch (IllegalStateException e) {
89                 Log.w(TAG, "Exception when trying to stop media player");
90             }
91             mMediaPlayer = null;
92         }
93 
94         resetAlarmVolume();
95     }
96 
setAlarmVolumeToFull()97     private void setAlarmVolumeToFull() {
98         int streamType = AudioManager.STREAM_ALARM;
99         if (mUserSetAlarmVolume == USER_SET_ALARM_VOLUME_UNKNOWN) {
100             mUserSetAlarmVolume = mAudioManager.getStreamVolume(streamType);
101         }
102         mResetAlarmVolumeNeeded = true;
103 
104         Log.d(TAG, "Setting alarm volume from " + mUserSetAlarmVolume + "to full");
105         mAudioManager.setStreamVolume(streamType,
106                 mAudioManager.getStreamMaxVolume(streamType), 0);
107     }
108 
resetAlarmVolume()109     private void resetAlarmVolume() {
110         if (mResetAlarmVolumeNeeded) {
111             Log.d(TAG, "Resetting alarm volume to back to " + mUserSetAlarmVolume);
112             mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, mUserSetAlarmVolume, 0);
113             mResetAlarmVolumeNeeded = false;
114         }
115     }
116 
isPlayWarningSoundEnabled()117     private boolean isPlayWarningSoundEnabled() {
118         return Settings.Secure.getInt(mContext.getContentResolver(),
119                 Settings.Secure.EMERGENCY_GESTURE_SOUND_ENABLED,
120                 EmergencyActionUtils.isDefaultEmergencyGestureSoundEnabled(mContext) ? 1 : 0) != 0;
121     }
122 }
123