1 /* 2 * Copyright (C) 2014 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.preference; 18 19 import android.annotation.NonNull; 20 import android.app.NotificationManager; 21 import android.compat.annotation.UnsupportedAppUsage; 22 import android.content.BroadcastReceiver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.database.ContentObserver; 27 import android.media.AudioAttributes; 28 import android.media.AudioManager; 29 import android.media.Ringtone; 30 import android.media.RingtoneManager; 31 import android.media.audiopolicy.AudioProductStrategy; 32 import android.media.audiopolicy.AudioVolumeGroup; 33 import android.net.Uri; 34 import android.os.Handler; 35 import android.os.HandlerThread; 36 import android.os.Message; 37 import android.preference.VolumePreference.VolumeStore; 38 import android.provider.Settings; 39 import android.provider.Settings.Global; 40 import android.provider.Settings.System; 41 import android.service.notification.ZenModeConfig; 42 import android.util.Log; 43 import android.widget.SeekBar; 44 import android.widget.SeekBar.OnSeekBarChangeListener; 45 46 import com.android.internal.annotations.GuardedBy; 47 import com.android.internal.os.SomeArgs; 48 49 /** 50 * Turns a {@link SeekBar} into a volume control. 51 * @hide 52 * 53 * @deprecated Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a> 54 * <a href="{@docRoot}reference/androidx/preference/package-summary.html"> 55 * Preference Library</a> for consistent behavior across all devices. For more information on 56 * using the AndroidX Preference Library see 57 * <a href="{@docRoot}guide/topics/ui/settings.html">Settings</a>. 58 */ 59 @Deprecated 60 public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callback { 61 private static final String TAG = "SeekBarVolumizer"; 62 63 public interface Callback { onSampleStarting(SeekBarVolumizer sbv)64 void onSampleStarting(SeekBarVolumizer sbv); onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch)65 void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch); onMuted(boolean muted, boolean zenMuted)66 void onMuted(boolean muted, boolean zenMuted); 67 } 68 69 private static final int MSG_GROUP_VOLUME_CHANGED = 1; 70 private final Handler mVolumeHandler = new VolumeHandler(); 71 private AudioAttributes mAttributes; 72 private int mVolumeGroupId; 73 74 private final AudioManager.VolumeGroupCallback mVolumeGroupCallback = 75 new AudioManager.VolumeGroupCallback() { 76 @Override 77 public void onAudioVolumeGroupChanged(int group, int flags) { 78 if (mHandler == null) { 79 return; 80 } 81 SomeArgs args = SomeArgs.obtain(); 82 args.arg1 = group; 83 args.arg2 = flags; 84 mVolumeHandler.sendMessage(mHandler.obtainMessage(MSG_GROUP_VOLUME_CHANGED, args)); 85 } 86 }; 87 88 @UnsupportedAppUsage 89 private final Context mContext; 90 private final H mUiHandler = new H(); 91 private final Callback mCallback; 92 private final Uri mDefaultUri; 93 @UnsupportedAppUsage 94 private final AudioManager mAudioManager; 95 private final NotificationManager mNotificationManager; 96 @UnsupportedAppUsage 97 private final int mStreamType; 98 private final int mMaxStreamVolume; 99 private boolean mAffectedByRingerMode; 100 private boolean mNotificationOrRing; 101 private final Receiver mReceiver = new Receiver(); 102 103 private Handler mHandler; 104 private Observer mVolumeObserver; 105 @UnsupportedAppUsage 106 private int mOriginalStreamVolume; 107 private int mLastAudibleStreamVolume; 108 // When the old handler is destroyed and a new one is created, there could be a situation where 109 // this is accessed at the same time in different handlers. So, access to this field needs to be 110 // synchronized. 111 @GuardedBy("this") 112 @UnsupportedAppUsage 113 private Ringtone mRingtone; 114 @UnsupportedAppUsage 115 private int mLastProgress = -1; 116 private boolean mMuted; 117 @UnsupportedAppUsage 118 private SeekBar mSeekBar; 119 private int mVolumeBeforeMute = -1; 120 private int mRingerMode; 121 private int mZenMode; 122 private boolean mPlaySample; 123 124 private static final int MSG_SET_STREAM_VOLUME = 0; 125 private static final int MSG_START_SAMPLE = 1; 126 private static final int MSG_STOP_SAMPLE = 2; 127 private static final int MSG_INIT_SAMPLE = 3; 128 private static final int CHECK_RINGTONE_PLAYBACK_DELAY_MS = 1000; 129 130 private NotificationManager.Policy mNotificationPolicy; 131 private boolean mAllowAlarms; 132 private boolean mAllowMedia; 133 private boolean mAllowRinger; 134 135 @UnsupportedAppUsage SeekBarVolumizer(Context context, int streamType, Uri defaultUri, Callback callback)136 public SeekBarVolumizer(Context context, int streamType, Uri defaultUri, Callback callback) { 137 this(context, streamType, defaultUri, callback, true /* playSample */); 138 } 139 SeekBarVolumizer( Context context, int streamType, Uri defaultUri, Callback callback, boolean playSample)140 public SeekBarVolumizer( 141 Context context, 142 int streamType, 143 Uri defaultUri, 144 Callback callback, 145 boolean playSample) { 146 mContext = context; 147 mAudioManager = context.getSystemService(AudioManager.class); 148 mNotificationManager = context.getSystemService(NotificationManager.class); 149 mNotificationPolicy = mNotificationManager.getConsolidatedNotificationPolicy(); 150 mAllowAlarms = (mNotificationPolicy.priorityCategories & NotificationManager.Policy 151 .PRIORITY_CATEGORY_ALARMS) != 0; 152 mAllowMedia = (mNotificationPolicy.priorityCategories & NotificationManager.Policy 153 .PRIORITY_CATEGORY_MEDIA) != 0; 154 mAllowRinger = !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted( 155 mNotificationPolicy); 156 mStreamType = streamType; 157 mAffectedByRingerMode = mAudioManager.isStreamAffectedByRingerMode(mStreamType); 158 mNotificationOrRing = isNotificationOrRing(mStreamType); 159 if (mNotificationOrRing) { 160 mRingerMode = mAudioManager.getRingerModeInternal(); 161 } 162 mZenMode = mNotificationManager.getZenMode(); 163 164 if (hasAudioProductStrategies()) { 165 mVolumeGroupId = getVolumeGroupIdForLegacyStreamType(mStreamType); 166 mAttributes = getAudioAttributesForLegacyStreamType( 167 mStreamType); 168 } 169 170 mMaxStreamVolume = mAudioManager.getStreamMaxVolume(mStreamType); 171 mCallback = callback; 172 mOriginalStreamVolume = mAudioManager.getStreamVolume(mStreamType); 173 mLastAudibleStreamVolume = mAudioManager.getLastAudibleStreamVolume(mStreamType); 174 mMuted = mAudioManager.isStreamMute(mStreamType); 175 mPlaySample = playSample; 176 if (mCallback != null) { 177 mCallback.onMuted(mMuted, isZenMuted()); 178 } 179 if (defaultUri == null) { 180 if (mStreamType == AudioManager.STREAM_RING) { 181 defaultUri = Settings.System.DEFAULT_RINGTONE_URI; 182 } else if (mStreamType == AudioManager.STREAM_NOTIFICATION) { 183 defaultUri = Settings.System.DEFAULT_NOTIFICATION_URI; 184 } else { 185 defaultUri = Settings.System.DEFAULT_ALARM_ALERT_URI; 186 } 187 } 188 mDefaultUri = defaultUri; 189 } 190 hasAudioProductStrategies()191 private boolean hasAudioProductStrategies() { 192 return AudioManager.getAudioProductStrategies().size() > 0; 193 } 194 getVolumeGroupIdForLegacyStreamType(int streamType)195 private int getVolumeGroupIdForLegacyStreamType(int streamType) { 196 for (final AudioProductStrategy productStrategy : 197 AudioManager.getAudioProductStrategies()) { 198 int volumeGroupId = productStrategy.getVolumeGroupIdForLegacyStreamType(streamType); 199 if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) { 200 return volumeGroupId; 201 } 202 } 203 204 return AudioManager.getAudioProductStrategies().stream() 205 .map(strategy -> strategy.getVolumeGroupIdForAudioAttributes( 206 AudioProductStrategy.sDefaultAttributes)) 207 .filter(volumeGroupId -> volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) 208 .findFirst() 209 .orElse(AudioVolumeGroup.DEFAULT_VOLUME_GROUP); 210 } 211 getAudioAttributesForLegacyStreamType(int streamType)212 private @NonNull AudioAttributes getAudioAttributesForLegacyStreamType(int streamType) { 213 for (final AudioProductStrategy productStrategy : 214 AudioManager.getAudioProductStrategies()) { 215 AudioAttributes aa = productStrategy.getAudioAttributesForLegacyStreamType(streamType); 216 if (aa != null) { 217 return aa; 218 } 219 } 220 return new AudioAttributes.Builder() 221 .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) 222 .setUsage(AudioAttributes.USAGE_UNKNOWN).build(); 223 } 224 isNotificationOrRing(int stream)225 private static boolean isNotificationOrRing(int stream) { 226 return stream == AudioManager.STREAM_RING || stream == AudioManager.STREAM_NOTIFICATION; 227 } 228 isAlarmsStream(int stream)229 private static boolean isAlarmsStream(int stream) { 230 return stream == AudioManager.STREAM_ALARM; 231 } 232 isMediaStream(int stream)233 private static boolean isMediaStream(int stream) { 234 return stream == AudioManager.STREAM_MUSIC; 235 } 236 setSeekBar(SeekBar seekBar)237 public void setSeekBar(SeekBar seekBar) { 238 if (mSeekBar != null) { 239 mSeekBar.setOnSeekBarChangeListener(null); 240 } 241 mSeekBar = seekBar; 242 mSeekBar.setOnSeekBarChangeListener(null); 243 mSeekBar.setMax(mMaxStreamVolume); 244 updateSeekBar(); 245 mSeekBar.setOnSeekBarChangeListener(this); 246 } 247 isZenMuted()248 private boolean isZenMuted() { 249 return mNotificationOrRing && mZenMode == Global.ZEN_MODE_ALARMS 250 || mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS 251 || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS 252 && ((!mAllowAlarms && isAlarmsStream(mStreamType)) 253 || (!mAllowMedia && isMediaStream(mStreamType)) 254 || (!mAllowRinger && isNotificationOrRing(mStreamType)))); 255 } 256 updateSeekBar()257 protected void updateSeekBar() { 258 final boolean zenMuted = isZenMuted(); 259 mSeekBar.setEnabled(!zenMuted); 260 if (zenMuted) { 261 mSeekBar.setProgress(mLastAudibleStreamVolume, true); 262 } else if (mNotificationOrRing && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) { 263 mSeekBar.setProgress(0, true); 264 } else if (mMuted) { 265 mSeekBar.setProgress(0, true); 266 } else { 267 mSeekBar.setProgress(mLastProgress > -1 ? mLastProgress : mOriginalStreamVolume, true); 268 } 269 } 270 271 @Override handleMessage(Message msg)272 public boolean handleMessage(Message msg) { 273 switch (msg.what) { 274 case MSG_SET_STREAM_VOLUME: 275 if (mMuted && mLastProgress > 0) { 276 mAudioManager.adjustStreamVolume(mStreamType, AudioManager.ADJUST_UNMUTE, 0); 277 } else if (!mMuted && mLastProgress == 0) { 278 mAudioManager.adjustStreamVolume(mStreamType, AudioManager.ADJUST_MUTE, 0); 279 } 280 mAudioManager.setStreamVolume(mStreamType, mLastProgress, 281 AudioManager.FLAG_SHOW_UI_WARNINGS); 282 break; 283 case MSG_START_SAMPLE: 284 if (mPlaySample) { 285 onStartSample(); 286 } 287 break; 288 case MSG_STOP_SAMPLE: 289 if (mPlaySample) { 290 onStopSample(); 291 } 292 break; 293 case MSG_INIT_SAMPLE: 294 if (mPlaySample) { 295 onInitSample(); 296 } 297 break; 298 default: 299 Log.e(TAG, "invalid SeekBarVolumizer message: "+msg.what); 300 } 301 return true; 302 } 303 onInitSample()304 private void onInitSample() { 305 synchronized (this) { 306 mRingtone = RingtoneManager.getRingtone(mContext, mDefaultUri); 307 if (mRingtone != null) { 308 mRingtone.setStreamType(mStreamType); 309 } 310 } 311 } 312 postStartSample()313 private void postStartSample() { 314 if (mHandler == null) return; 315 mHandler.removeMessages(MSG_START_SAMPLE); 316 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_SAMPLE), 317 isSamplePlaying() ? CHECK_RINGTONE_PLAYBACK_DELAY_MS : 0); 318 } 319 onStartSample()320 private void onStartSample() { 321 if (!isSamplePlaying()) { 322 if (mCallback != null) { 323 mCallback.onSampleStarting(this); 324 } 325 326 synchronized (this) { 327 if (mRingtone != null) { 328 try { 329 mRingtone.setAudioAttributes(new AudioAttributes.Builder(mRingtone 330 .getAudioAttributes()) 331 .setFlags(AudioAttributes.FLAG_BYPASS_MUTE) 332 .build()); 333 mRingtone.play(); 334 } catch (Throwable e) { 335 Log.w(TAG, "Error playing ringtone, stream " + mStreamType, e); 336 } 337 } 338 } 339 } 340 } 341 postStopSample()342 private void postStopSample() { 343 if (mHandler == null) return; 344 // remove pending delayed start messages 345 mHandler.removeMessages(MSG_START_SAMPLE); 346 mHandler.removeMessages(MSG_STOP_SAMPLE); 347 mHandler.sendMessage(mHandler.obtainMessage(MSG_STOP_SAMPLE)); 348 } 349 onStopSample()350 private void onStopSample() { 351 synchronized (this) { 352 if (mRingtone != null) { 353 mRingtone.stop(); 354 } 355 } 356 } 357 358 @UnsupportedAppUsage stop()359 public void stop() { 360 if (mHandler == null) return; // already stopped 361 postStopSample(); 362 mContext.getContentResolver().unregisterContentObserver(mVolumeObserver); 363 mReceiver.setListening(false); 364 if (hasAudioProductStrategies()) { 365 unregisterVolumeGroupCb(); 366 } 367 mSeekBar.setOnSeekBarChangeListener(null); 368 mHandler.getLooper().quitSafely(); 369 mHandler = null; 370 mVolumeObserver = null; 371 } 372 start()373 public void start() { 374 if (mHandler != null) return; // already started 375 HandlerThread thread = new HandlerThread(TAG + ".CallbackHandler"); 376 thread.start(); 377 mHandler = new Handler(thread.getLooper(), this); 378 mHandler.sendEmptyMessage(MSG_INIT_SAMPLE); 379 mVolumeObserver = new Observer(mHandler); 380 mContext.getContentResolver().registerContentObserver( 381 System.getUriFor(System.VOLUME_SETTINGS_INT[mStreamType]), 382 false, mVolumeObserver); 383 mReceiver.setListening(true); 384 if (hasAudioProductStrategies()) { 385 registerVolumeGroupCb(); 386 } 387 } 388 revertVolume()389 public void revertVolume() { 390 mAudioManager.setStreamVolume(mStreamType, mOriginalStreamVolume, 0); 391 } 392 onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch)393 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) { 394 if (fromTouch) { 395 postSetVolume(progress); 396 } 397 if (mCallback != null) { 398 mCallback.onProgressChanged(seekBar, progress, fromTouch); 399 } 400 } 401 postSetVolume(int progress)402 private void postSetVolume(int progress) { 403 if (mHandler == null) return; 404 // Do the volume changing separately to give responsive UI 405 mLastProgress = progress; 406 mHandler.removeMessages(MSG_SET_STREAM_VOLUME); 407 mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_STREAM_VOLUME)); 408 } 409 onStartTrackingTouch(SeekBar seekBar)410 public void onStartTrackingTouch(SeekBar seekBar) { 411 } 412 onStopTrackingTouch(SeekBar seekBar)413 public void onStopTrackingTouch(SeekBar seekBar) { 414 postStartSample(); 415 } 416 isSamplePlaying()417 public boolean isSamplePlaying() { 418 synchronized (this) { 419 return mRingtone != null && mRingtone.isPlaying(); 420 } 421 } 422 startSample()423 public void startSample() { 424 postStartSample(); 425 } 426 stopSample()427 public void stopSample() { 428 postStopSample(); 429 } 430 getSeekBar()431 public SeekBar getSeekBar() { 432 return mSeekBar; 433 } 434 changeVolumeBy(int amount)435 public void changeVolumeBy(int amount) { 436 mSeekBar.incrementProgressBy(amount); 437 postSetVolume(mSeekBar.getProgress()); 438 postStartSample(); 439 mVolumeBeforeMute = -1; 440 } 441 muteVolume()442 public void muteVolume() { 443 if (mVolumeBeforeMute != -1) { 444 mSeekBar.setProgress(mVolumeBeforeMute, true); 445 postSetVolume(mVolumeBeforeMute); 446 postStartSample(); 447 mVolumeBeforeMute = -1; 448 } else { 449 mVolumeBeforeMute = mSeekBar.getProgress(); 450 mSeekBar.setProgress(0, true); 451 postStopSample(); 452 postSetVolume(0); 453 } 454 } 455 onSaveInstanceState(VolumeStore volumeStore)456 public void onSaveInstanceState(VolumeStore volumeStore) { 457 if (mLastProgress >= 0) { 458 volumeStore.volume = mLastProgress; 459 volumeStore.originalVolume = mOriginalStreamVolume; 460 } 461 } 462 onRestoreInstanceState(VolumeStore volumeStore)463 public void onRestoreInstanceState(VolumeStore volumeStore) { 464 if (volumeStore.volume != -1) { 465 mOriginalStreamVolume = volumeStore.originalVolume; 466 mLastProgress = volumeStore.volume; 467 postSetVolume(mLastProgress); 468 } 469 } 470 471 private final class H extends Handler { 472 private static final int UPDATE_SLIDER = 1; 473 474 @Override handleMessage(Message msg)475 public void handleMessage(Message msg) { 476 if (msg.what == UPDATE_SLIDER) { 477 if (mSeekBar != null) { 478 mLastProgress = msg.arg1; 479 mLastAudibleStreamVolume = msg.arg2; 480 final boolean muted = ((Boolean)msg.obj).booleanValue(); 481 if (muted != mMuted) { 482 mMuted = muted; 483 if (mCallback != null) { 484 mCallback.onMuted(mMuted, isZenMuted()); 485 } 486 } 487 updateSeekBar(); 488 } 489 } 490 } 491 postUpdateSlider(int volume, int lastAudibleVolume, boolean mute)492 public void postUpdateSlider(int volume, int lastAudibleVolume, boolean mute) { 493 obtainMessage(UPDATE_SLIDER, volume, lastAudibleVolume, new Boolean(mute)).sendToTarget(); 494 } 495 } 496 updateSlider()497 private void updateSlider() { 498 if (mSeekBar != null && mAudioManager != null) { 499 final int volume = mAudioManager.getStreamVolume(mStreamType); 500 final int lastAudibleVolume = mAudioManager.getLastAudibleStreamVolume(mStreamType); 501 final boolean mute = mAudioManager.isStreamMute(mStreamType); 502 mUiHandler.postUpdateSlider(volume, lastAudibleVolume, mute); 503 } 504 } 505 506 private final class Observer extends ContentObserver { Observer(Handler handler)507 public Observer(Handler handler) { 508 super(handler); 509 } 510 511 @Override onChange(boolean selfChange)512 public void onChange(boolean selfChange) { 513 super.onChange(selfChange); 514 updateSlider(); 515 } 516 } 517 518 private final class Receiver extends BroadcastReceiver { 519 private boolean mListening; 520 setListening(boolean listening)521 public void setListening(boolean listening) { 522 if (mListening == listening) return; 523 mListening = listening; 524 if (listening) { 525 final IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION); 526 filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION); 527 filter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED); 528 filter.addAction(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED); 529 filter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION); 530 mContext.registerReceiver(this, filter); 531 } else { 532 mContext.unregisterReceiver(this); 533 } 534 } 535 536 @Override onReceive(Context context, Intent intent)537 public void onReceive(Context context, Intent intent) { 538 final String action = intent.getAction(); 539 if (AudioManager.VOLUME_CHANGED_ACTION.equals(action)) { 540 int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); 541 int streamValue = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1); 542 if (hasAudioProductStrategies()) { 543 updateVolumeSlider(streamType, streamValue); 544 } 545 } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) { 546 if (mNotificationOrRing) { 547 mRingerMode = mAudioManager.getRingerModeInternal(); 548 } 549 if (mAffectedByRingerMode) { 550 updateSlider(); 551 } 552 } else if (AudioManager.STREAM_DEVICES_CHANGED_ACTION.equals(action)) { 553 int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); 554 if (hasAudioProductStrategies()) { 555 int streamVolume = mAudioManager.getStreamVolume(streamType); 556 updateVolumeSlider(streamType, streamVolume); 557 } else { 558 int volumeGroup = getVolumeGroupIdForLegacyStreamType(streamType); 559 if (volumeGroup != AudioVolumeGroup.DEFAULT_VOLUME_GROUP 560 && volumeGroup == mVolumeGroupId) { 561 int streamVolume = mAudioManager.getStreamVolume(streamType); 562 updateVolumeSlider(streamType, streamVolume); 563 } 564 } 565 } else if (NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED.equals(action)) { 566 mZenMode = mNotificationManager.getZenMode(); 567 updateSlider(); 568 } else if (NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED.equals(action)) { 569 mNotificationPolicy = mNotificationManager.getConsolidatedNotificationPolicy(); 570 mAllowAlarms = (mNotificationPolicy.priorityCategories & NotificationManager.Policy 571 .PRIORITY_CATEGORY_ALARMS) != 0; 572 mAllowMedia = (mNotificationPolicy.priorityCategories 573 & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) != 0; 574 mAllowRinger = !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted( 575 mNotificationPolicy); 576 updateSlider(); 577 } 578 } 579 updateVolumeSlider(int streamType, int streamValue)580 private void updateVolumeSlider(int streamType, int streamValue) { 581 final boolean streamMatch = mNotificationOrRing ? isNotificationOrRing(streamType) 582 : (streamType == mStreamType); 583 if (mSeekBar != null && streamMatch && streamValue != -1) { 584 final boolean muted = mAudioManager.isStreamMute(mStreamType) 585 || streamValue == 0; 586 mUiHandler.postUpdateSlider(streamValue, mLastAudibleStreamVolume, muted); 587 } 588 } 589 } 590 registerVolumeGroupCb()591 private void registerVolumeGroupCb() { 592 if (mVolumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) { 593 mAudioManager.registerVolumeGroupCallback(Runnable::run, mVolumeGroupCallback); 594 updateSlider(); 595 } 596 } 597 unregisterVolumeGroupCb()598 private void unregisterVolumeGroupCb() { 599 if (mVolumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) { 600 mAudioManager.unregisterVolumeGroupCallback(mVolumeGroupCallback); 601 } 602 } 603 604 private class VolumeHandler extends Handler { 605 @Override handleMessage(Message msg)606 public void handleMessage(Message msg) { 607 SomeArgs args = (SomeArgs) msg.obj; 608 switch (msg.what) { 609 case MSG_GROUP_VOLUME_CHANGED: 610 int group = (int) args.arg1; 611 if (mVolumeGroupId != group 612 || mVolumeGroupId == AudioVolumeGroup.DEFAULT_VOLUME_GROUP) { 613 return; 614 } 615 updateSlider(); 616 break; 617 } 618 } 619 } 620 } 621