Skip to content

Commit bc0fab1

Browse files
author
Eric Laurent
committed
Add multi user volume management
Notification and Alarm volumes are per user: they are saved and restored when the foreground user changes. Media volume is global: it is still saved and restored per user for implentation reasons but is copied from one user to the next to ensure media playback volume continuity when switching users. Ringer mode (silent, vibrate...) is now a global setting. Bug 7128886. Change-Id: I9f4f5a0a3985552bca61c2cc3bbe5a144db755a6
1 parent c31f5a7 commit bc0fab1

File tree

3 files changed

+78
-37
lines changed

3 files changed

+78
-37
lines changed

api/current.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18797,6 +18797,7 @@ package android.provider {
1879718797
field public static final java.lang.String DEVELOPMENT_SETTINGS_ENABLED = "development_settings_enabled";
1879818798
field public static final java.lang.String DEVICE_PROVISIONED = "device_provisioned";
1879918799
field public static final java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
18800+
field public static final java.lang.String MODE_RINGER = "mode_ringer";
1880018801
field public static final java.lang.String NETWORK_PREFERENCE = "network_preference";
1880118802
field public static final java.lang.String RADIO_BLUETOOTH = "bluetooth";
1880218803
field public static final java.lang.String RADIO_CELL = "cell";
@@ -18960,7 +18961,7 @@ package android.provider {
1896018961
field public static final deprecated java.lang.String LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED = "lock_pattern_tactile_feedback_enabled";
1896118962
field public static final deprecated java.lang.String LOCK_PATTERN_VISIBLE = "lock_pattern_visible_pattern";
1896218963
field public static final deprecated java.lang.String LOGGING_ID = "logging_id";
18963-
field public static final java.lang.String MODE_RINGER = "mode_ringer";
18964+
field public static final deprecated java.lang.String MODE_RINGER = "mode_ringer";
1896418965
field public static final java.lang.String MODE_RINGER_STREAMS_AFFECTED = "mode_ringer_streams_affected";
1896518966
field public static final java.lang.String MUTE_STREAMS_AFFECTED = "mute_streams_affected";
1896618967
field public static final deprecated java.lang.String NETWORK_PREFERENCE = "network_preference";

core/java/android/provider/Settings.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,7 @@ public static final class System extends NameValueTable {
919919
MOVED_TO_GLOBAL.add(Settings.Global.POWER_SOUNDS_ENABLED);
920920
MOVED_TO_GLOBAL.add(Settings.Global.STAY_ON_WHILE_PLUGGED_IN);
921921
MOVED_TO_GLOBAL.add(Settings.Global.WIFI_SLEEP_POLICY);
922+
MOVED_TO_GLOBAL.add(Settings.Global.MODE_RINGER);
922923
}
923924

924925
private static void lazyInitCache() {
@@ -1482,6 +1483,12 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
14821483
@Deprecated
14831484
public static final int WIFI_SLEEP_POLICY_NEVER = Global.WIFI_SLEEP_POLICY_NEVER;
14841485

1486+
/**
1487+
* @deprecated Use {@link android.provider.Settings.Global#MODE_RINGER} instead
1488+
*/
1489+
@Deprecated
1490+
public static final String MODE_RINGER = Global.MODE_RINGER;
1491+
14851492
//TODO: deprecate static IP constants
14861493
/**
14871494
* Whether to use static IP and other static network attributes.
@@ -1651,13 +1658,6 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
16511658
public static final String ALWAYS_FINISH_ACTIVITIES =
16521659
"always_finish_activities";
16531660

1654-
1655-
/**
1656-
* Ringer mode. This is used internally, changing this value will not
1657-
* change the ringer mode. See AudioManager.
1658-
*/
1659-
public static final String MODE_RINGER = "mode_ringer";
1660-
16611661
/**
16621662
* Determines which streams are affected by ringer mode changes. The
16631663
* stream type's bit should be set to 1 if it should be muted when going
@@ -5709,7 +5709,11 @@ public static final class Global extends NameValueTable {
57095709
*/
57105710
public static final String WTF_IS_FATAL = "wtf_is_fatal";
57115711

5712-
5712+
/**
5713+
* Ringer mode. This is used internally, changing this value will not
5714+
* change the ringer mode. See AudioManager.
5715+
*/
5716+
public static final String MODE_RINGER = "mode_ringer";
57135717

57145718

57155719
// Populated lazily, guarded by class object:

media/java/android/media/AudioService.java

Lines changed: 64 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ public AudioService(Context context) {
480480
intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
481481
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
482482
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
483+
intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
483484

484485
// Register a configuration change listener only if requested by system properties
485486
// to monitor orientation changes (off by default)
@@ -608,7 +609,7 @@ private void readPersistedSettings() {
608609
final ContentResolver cr = mContentResolver;
609610

610611
int ringerModeFromSettings =
611-
System.getInt(cr, System.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
612+
Settings.Global.getInt(cr, System.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
612613
int ringerMode = ringerModeFromSettings;
613614
// sanity check in case the settings are restored from a device with incompatible
614615
// ringer modes
@@ -619,7 +620,7 @@ private void readPersistedSettings() {
619620
ringerMode = AudioManager.RINGER_MODE_SILENT;
620621
}
621622
if (ringerMode != ringerModeFromSettings) {
622-
System.putInt(cr, System.MODE_RINGER, ringerMode);
623+
Settings.Global.putInt(cr, System.MODE_RINGER, ringerMode);
623624
}
624625
synchronized(mSettingsLock) {
625626
mRingerMode = ringerMode;
@@ -638,23 +639,30 @@ private void readPersistedSettings() {
638639

639640
// make sure settings for ringer mode are consistent with device type: non voice capable
640641
// devices (tablets) include media stream in silent mode whereas phones don't.
641-
mRingerModeAffectedStreams = Settings.System.getInt(cr,
642+
mRingerModeAffectedStreams = Settings.System.getIntForUser(cr,
642643
Settings.System.MODE_RINGER_STREAMS_AFFECTED,
643644
((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
644-
(1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)));
645+
(1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
646+
UserHandle.USER_CURRENT);
645647
if (mVoiceCapable) {
646648
mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
647649
} else {
648650
mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC);
649651
}
650-
Settings.System.putInt(cr,
651-
Settings.System.MODE_RINGER_STREAMS_AFFECTED, mRingerModeAffectedStreams);
652+
Settings.System.putIntForUser(cr,
653+
Settings.System.MODE_RINGER_STREAMS_AFFECTED,
654+
mRingerModeAffectedStreams,
655+
UserHandle.USER_CURRENT);
652656

653-
mMuteAffectedStreams = System.getInt(cr,
657+
mMuteAffectedStreams = System.getIntForUser(cr,
654658
System.MUTE_STREAMS_AFFECTED,
655-
((1 << AudioSystem.STREAM_MUSIC)|(1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_SYSTEM)));
659+
((1 << AudioSystem.STREAM_MUSIC)|
660+
(1 << AudioSystem.STREAM_RING)|
661+
(1 << AudioSystem.STREAM_SYSTEM)),
662+
UserHandle.USER_CURRENT);
656663

657-
boolean masterMute = System.getInt(cr, System.VOLUME_MASTER_MUTE, 0) == 1;
664+
boolean masterMute = System.getIntForUser(cr, System.VOLUME_MASTER_MUTE,
665+
0, UserHandle.USER_CURRENT) == 1;
658666
AudioSystem.setMasterMute(masterMute);
659667
broadcastMasterMuteStatus(masterMute);
660668

@@ -1237,8 +1245,8 @@ private void setRingerModeInt(int ringerMode, boolean persist) {
12371245

12381246
private void restoreMasterVolume() {
12391247
if (mUseMasterVolume) {
1240-
float volume = Settings.System.getFloat(mContentResolver,
1241-
Settings.System.VOLUME_MASTER, -1.0f);
1248+
float volume = Settings.System.getFloatForUser(mContentResolver,
1249+
Settings.System.VOLUME_MASTER, -1.0f, UserHandle.USER_CURRENT);
12421250
if (volume >= 0.0f) {
12431251
AudioSystem.setMasterVolume(volume);
12441252
}
@@ -1674,6 +1682,10 @@ public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
16741682

16751683
/** @see AudioManager#reloadAudioSettings() */
16761684
public void reloadAudioSettings() {
1685+
readAudioSettings(false /*userSwitch*/);
1686+
}
1687+
1688+
private void readAudioSettings(boolean userSwitch) {
16771689
// restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
16781690
readPersistedSettings();
16791691

@@ -1682,6 +1694,10 @@ public void reloadAudioSettings() {
16821694
for (int streamType = 0; streamType < numStreamTypes; streamType++) {
16831695
VolumeStreamState streamState = mStreamStates[streamType];
16841696

1697+
if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) {
1698+
continue;
1699+
}
1700+
16851701
synchronized (streamState) {
16861702
streamState.readSettings();
16871703

@@ -2536,7 +2552,8 @@ public synchronized void readSettings() {
25362552
// device, continue otherwise
25372553
int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
25382554
AudioManager.DEFAULT_STREAM_VOLUME[mStreamType] : -1;
2539-
int index = Settings.System.getInt(mContentResolver, name, defaultIndex);
2555+
int index = Settings.System.getIntForUser(
2556+
mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
25402557
if (index == -1) {
25412558
continue;
25422559
}
@@ -2547,7 +2564,8 @@ public synchronized void readSettings() {
25472564
// or default index
25482565
defaultIndex = (index > 0) ?
25492566
index : AudioManager.DEFAULT_STREAM_VOLUME[mStreamType];
2550-
int lastAudibleIndex = Settings.System.getInt(mContentResolver, name, defaultIndex);
2567+
int lastAudibleIndex = Settings.System.getIntForUser(
2568+
mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
25512569

25522570
// a last audible index of 0 should never be stored for ring and notification
25532571
// streams on phones (voice capable devices).
@@ -2959,19 +2977,21 @@ private void persistVolume(VolumeStreamState streamState,
29592977
int persistType,
29602978
int device) {
29612979
if ((persistType & PERSIST_CURRENT) != 0) {
2962-
System.putInt(mContentResolver,
2980+
System.putIntForUser(mContentResolver,
29632981
streamState.getSettingNameForDevice(false /* lastAudible */, device),
2964-
(streamState.getIndex(device, false /* lastAudible */) + 5)/ 10);
2982+
(streamState.getIndex(device, false /* lastAudible */) + 5)/ 10,
2983+
UserHandle.USER_CURRENT);
29652984
}
29662985
if ((persistType & PERSIST_LAST_AUDIBLE) != 0) {
2967-
System.putInt(mContentResolver,
2986+
System.putIntForUser(mContentResolver,
29682987
streamState.getSettingNameForDevice(true /* lastAudible */, device),
2969-
(streamState.getIndex(device, true /* lastAudible */) + 5) / 10);
2988+
(streamState.getIndex(device, true /* lastAudible */) + 5) / 10,
2989+
UserHandle.USER_CURRENT);
29702990
}
29712991
}
29722992

29732993
private void persistRingerMode(int ringerMode) {
2974-
System.putInt(mContentResolver, System.MODE_RINGER, ringerMode);
2994+
Settings.Global.putInt(mContentResolver, System.MODE_RINGER, ringerMode);
29752995
}
29762996

29772997
private void playSoundEffect(int effectType, int volume) {
@@ -3021,8 +3041,10 @@ public boolean onError(MediaPlayer mp, int what, int extra) {
30213041
}
30223042

30233043
private void onHandlePersistMediaButtonReceiver(ComponentName receiver) {
3024-
Settings.System.putString(mContentResolver, Settings.System.MEDIA_BUTTON_RECEIVER,
3025-
receiver == null ? "" : receiver.flattenToString());
3044+
Settings.System.putStringForUser(mContentResolver,
3045+
Settings.System.MEDIA_BUTTON_RECEIVER,
3046+
receiver == null ? "" : receiver.flattenToString(),
3047+
UserHandle.USER_CURRENT);
30263048
}
30273049

30283050
private void cleanupPlayer(MediaPlayer mp) {
@@ -3058,13 +3080,17 @@ public void handleMessage(Message msg) {
30583080
break;
30593081

30603082
case MSG_PERSIST_MASTER_VOLUME:
3061-
Settings.System.putFloat(mContentResolver, Settings.System.VOLUME_MASTER,
3062-
(float)msg.arg1 / (float)1000.0);
3083+
Settings.System.putFloatForUser(mContentResolver,
3084+
Settings.System.VOLUME_MASTER,
3085+
(float)msg.arg1 / (float)1000.0,
3086+
UserHandle.USER_CURRENT);
30633087
break;
30643088

30653089
case MSG_PERSIST_MASTER_VOLUME_MUTE:
3066-
Settings.System.putInt(mContentResolver, Settings.System.VOLUME_MASTER_MUTE,
3067-
msg.arg1);
3090+
Settings.System.putIntForUser(mContentResolver,
3091+
Settings.System.VOLUME_MASTER_MUTE,
3092+
msg.arg1,
3093+
UserHandle.USER_CURRENT);
30683094
break;
30693095

30703096
case MSG_PERSIST_RINGER_MODE:
@@ -3248,10 +3274,11 @@ public void onChange(boolean selfChange) {
32483274
// and mRingerModeAffectedStreams, so will leave this synchronized for now.
32493275
// mRingerModeMutedStreams and mMuteAffectedStreams are safe (only accessed once).
32503276
synchronized (mSettingsLock) {
3251-
int ringerModeAffectedStreams = Settings.System.getInt(mContentResolver,
3277+
int ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
32523278
Settings.System.MODE_RINGER_STREAMS_AFFECTED,
32533279
((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
3254-
(1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)));
3280+
(1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
3281+
UserHandle.USER_CURRENT);
32553282
if (mVoiceCapable) {
32563283
ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC);
32573284
} else {
@@ -3670,6 +3697,15 @@ public void onReceive(Context context, Intent intent) {
36703697
AudioSystem.setParameters("screen_state=off");
36713698
} else if (action.equalsIgnoreCase(Intent.ACTION_CONFIGURATION_CHANGED)) {
36723699
handleConfigurationChanged(context);
3700+
} else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
3701+
readAudioSettings(true /*userSwitch*/);
3702+
// preserve STREAM_MUSIC volume from one user to the next.
3703+
sendMsg(mAudioHandler,
3704+
MSG_SET_ALL_VOLUMES,
3705+
SENDMSG_QUEUE,
3706+
0,
3707+
0,
3708+
mStreamStates[AudioSystem.STREAM_MUSIC], 0);
36733709
}
36743710
}
36753711
}
@@ -4544,8 +4580,8 @@ private void removeMediaButtonReceiverForPackage(String packageName) {
45444580
* Restore remote control receiver from the system settings.
45454581
*/
45464582
private void restoreMediaButtonReceiver() {
4547-
String receiverName = Settings.System.getString(mContentResolver,
4548-
Settings.System.MEDIA_BUTTON_RECEIVER);
4583+
String receiverName = Settings.System.getStringForUser(mContentResolver,
4584+
Settings.System.MEDIA_BUTTON_RECEIVER, UserHandle.USER_CURRENT);
45494585
if ((null != receiverName) && !receiverName.isEmpty()) {
45504586
ComponentName eventReceiver = ComponentName.unflattenFromString(receiverName);
45514587
// construct a PendingIntent targeted to the restored component name

0 commit comments

Comments
 (0)