OSDN Git Service

Settings: Always set ramp-up time value during bindView
[android-x86/packages-apps-Settings.git] / src / com / android / settings / notification / IncreasingRingVolumePreference.java
1 /*
2  * Copyright (C) 2014 CyanogenMod 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.settings.notification;
18
19 import android.content.ContentResolver;
20 import android.content.Context;
21 import android.media.AudioAttributes;
22 import android.media.AudioManager;
23 import android.media.Ringtone;
24 import android.media.RingtoneManager;
25 import android.os.Handler;
26 import android.os.HandlerThread;
27 import android.os.Message;
28 import android.preference.PreferenceManager;
29 import android.preference.Preference;
30 import android.provider.Settings;
31 import android.text.format.Formatter;
32 import android.util.AttributeSet;
33 import android.util.Log;
34 import android.view.View;
35 import android.widget.SeekBar;
36 import android.widget.TextView;
37
38 import com.android.settings.R;
39 import cyanogenmod.providers.CMSettings;
40
41 public class IncreasingRingVolumePreference extends Preference implements
42         PreferenceManager.OnActivityStopListener, Handler.Callback,
43         SeekBar.OnSeekBarChangeListener {
44     private static final String TAG = "IncreasingRingMinVolumePreference";
45
46     public interface Callback {
47         void onStartingSample();
48     }
49
50     private SeekBar mStartVolumeSeekBar;
51     private SeekBar mRampUpTimeSeekBar;
52     private TextView mRampUpTimeValue;
53
54     private Ringtone mRingtone;
55     private Callback mCallback;
56
57     private Handler mHandler;
58     private final Handler mMainHandler = new Handler(this);
59
60     private static final int MSG_START_SAMPLE = 1;
61     private static final int MSG_STOP_SAMPLE = 2;
62     private static final int MSG_INIT_SAMPLE = 3;
63     private static final int MSG_SET_VOLUME = 4;
64     private static final int CHECK_RINGTONE_PLAYBACK_DELAY_MS = 1000;
65
66     public IncreasingRingVolumePreference(Context context) {
67         this(context, null);
68     }
69
70     public IncreasingRingVolumePreference(Context context, AttributeSet attrs) {
71         this(context, attrs, 0);
72     }
73
74     public IncreasingRingVolumePreference(Context context, AttributeSet attrs,
75             int defStyleAttr) {
76         this(context, attrs, defStyleAttr, 0);
77     }
78
79     public IncreasingRingVolumePreference(Context context, AttributeSet attrs,
80             int defStyleAttr, int defStyleRes) {
81         super(context, attrs, defStyleAttr, defStyleRes);
82         setLayoutResource(R.layout.preference_increasing_ring);
83         initHandler();
84     }
85
86     public void setCallback(Callback callback) {
87         mCallback = callback;
88     }
89
90     public void onActivityResume() {
91         initHandler();
92     }
93
94     @Override
95     public void onActivityStop() {
96         if (mHandler != null) {
97             postStopSample();
98             mHandler.getLooper().quitSafely();
99             mHandler = null;
100         }
101     }
102
103     @Override
104     public boolean handleMessage(Message msg) {
105         switch (msg.what) {
106             case MSG_START_SAMPLE:
107                 onStartSample((float) msg.arg1 / 1000F);
108                 break;
109             case MSG_STOP_SAMPLE:
110                 onStopSample();
111                 break;
112             case MSG_INIT_SAMPLE:
113                 onInitSample();
114                 break;
115             case MSG_SET_VOLUME:
116                 onSetVolume((float) msg.arg1 / 1000F);
117                 break;
118         }
119         return true;
120     }
121
122     @Override
123     protected void onBindView(View view) {
124         super.onBindView(view);
125         getPreferenceManager().registerOnActivityStopListener(this);
126
127         initHandler();
128
129         final SeekBar seekBar = (SeekBar) view.findViewById(R.id.start_volume);
130         if (seekBar == mStartVolumeSeekBar) return;
131
132         mStartVolumeSeekBar = seekBar;
133         mRampUpTimeSeekBar = (SeekBar) view.findViewById(R.id.ramp_up_time);
134         mRampUpTimeValue = (TextView) view.findViewById(R.id.ramp_up_time_value);
135
136         final ContentResolver cr = getContext().getContentResolver();
137         float startVolume = CMSettings.System.getFloat(cr,
138                 CMSettings.System.INCREASING_RING_START_VOLUME, 0.1f);
139         int rampUpTime = CMSettings.System.getInt(cr,
140                 CMSettings.System.INCREASING_RING_RAMP_UP_TIME, 10);
141
142         mStartVolumeSeekBar.setProgress(Math.round(startVolume * 1000F));
143         mStartVolumeSeekBar.setOnSeekBarChangeListener(this);
144         mRampUpTimeSeekBar.setOnSeekBarChangeListener(this);
145         mRampUpTimeSeekBar.setProgress((rampUpTime / 5) - 1);
146         mRampUpTimeValue.setText(
147                 Formatter.formatShortElapsedTime(getContext(), rampUpTime * 1000));
148     }
149
150     @Override
151     public void onStartTrackingTouch(SeekBar seekBar) {
152     }
153
154     @Override
155     public void onStopTrackingTouch(SeekBar seekBar) {
156         if (seekBar == mStartVolumeSeekBar) {
157             postStartSample(seekBar.getProgress());
158         }
159     }
160
161     @Override
162     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
163         ContentResolver cr = getContext().getContentResolver();
164         if (fromTouch && seekBar == mStartVolumeSeekBar) {
165             CMSettings.System.putFloat(cr, CMSettings.System.INCREASING_RING_START_VOLUME,
166                         (float) progress / 1000F);
167         } else if (seekBar == mRampUpTimeSeekBar) {
168             int seconds = (progress + 1) * 5;
169             mRampUpTimeValue.setText(
170                     Formatter.formatShortElapsedTime(getContext(), seconds * 1000));
171             if (fromTouch) {
172                 CMSettings.System.putInt(cr,
173                         CMSettings.System.INCREASING_RING_RAMP_UP_TIME, seconds);
174             }
175         }
176     }
177
178     private void initHandler() {
179         if (mHandler != null) return;
180
181         HandlerThread thread = new HandlerThread(TAG + ".CallbackHandler");
182         thread.start();
183
184         mHandler = new Handler(thread.getLooper(), this);
185         mHandler.sendEmptyMessage(MSG_INIT_SAMPLE);
186     }
187
188     private void onInitSample() {
189         mRingtone = RingtoneManager.getRingtone(getContext(),
190                 Settings.System.DEFAULT_RINGTONE_URI);
191         if (mRingtone != null) {
192             mRingtone.setStreamType(AudioManager.STREAM_RING);
193             mRingtone.setAudioAttributes(
194                     new AudioAttributes.Builder(mRingtone.getAudioAttributes())
195                             .setFlags(AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY |
196                                     AudioAttributes.FLAG_BYPASS_MUTE)
197                             .build());
198         }
199     }
200
201     private void postStartSample(int progress) {
202         boolean playing = isSamplePlaying();
203         mHandler.removeMessages(MSG_START_SAMPLE);
204         mHandler.removeMessages(MSG_SET_VOLUME);
205         mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_SAMPLE, progress, 0),
206                 playing ? CHECK_RINGTONE_PLAYBACK_DELAY_MS : 0);
207         if (playing) {
208             mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_VOLUME, progress, 0));
209         }
210     }
211
212     private void onStartSample(float volume) {
213         if (mRingtone == null) {
214             return;
215         }
216         if (!isSamplePlaying()) {
217             if (mCallback != null) {
218                 mCallback.onStartingSample();
219             }
220             try {
221                 mRingtone.play();
222             } catch (Throwable e) {
223                 Log.w(TAG, "Error playing ringtone", e);
224             }
225         }
226         mRingtone.setVolume(volume);
227     }
228
229     private void onSetVolume(float volume) {
230         if (mRingtone != null) {
231             mRingtone.setVolume(volume);
232         }
233     }
234
235     private boolean isSamplePlaying() {
236         return mRingtone != null && mRingtone.isPlaying();
237     }
238
239     public void stopSample() {
240         if (mHandler != null) {
241             postStopSample();
242         }
243     }
244
245     private void postStopSample() {
246         // remove pending delayed start messages
247         mHandler.removeMessages(MSG_START_SAMPLE);
248         mHandler.removeMessages(MSG_STOP_SAMPLE);
249         mHandler.sendEmptyMessage(MSG_STOP_SAMPLE);
250     }
251
252     private void onStopSample() {
253         if (mRingtone != null) {
254             mRingtone.stop();
255         }
256     }
257 }