SystemUI VolumeService

来源:互联网 发布:ketchup mac免费 编辑:程序博客网 时间:2024/05/21 04:25
//当手机设备当前活动窗口在Launcher桌面,Launcher没有对音量事件做拦截操作,音量键事件将会在PhoneWindow中被消化。
protected boolean onKeyDown(int featureId, int keyCode, KeyEvent event) {
final KeyEvent.DispatcherState dispatcher =
mDecor != null ? mDecor.getKeyDispatcherState() : null;
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_MUTE: {
int direction = 0;
switch (keyCode) {
//direction为音量控制类型,为0时保持不变
case KeyEvent.KEYCODE_VOLUME_UP:
direction = AudioManager.ADJUST_RAISE;
break;
case KeyEvent.KEYCODE_VOLUME_DOWN:
direction = AudioManager.ADJUST_LOWER;
break;
case KeyEvent.KEYCODE_VOLUME_MUTE:
direction = AudioManager.ADJUST_TOGGLE_MUTE;
break;
}
if (mMediaController != null) {
mMediaController.adjustVolume(direction, AudioManager.FLAG_SHOW_UI);
} else {
//mVolumeControlStreamType表示音量类型
//direction表示音量控制类型
//第三个参数控制VolumeUI的显示
MediaSessionLegacyHelper.getHelper(getContext()).sendAdjustVolumeBy(
mVolumeControlStreamType, direction,
AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_VIBRATE
| AudioManager.FLAG_FROM_KEY);
}
return true;
}
...
}
return false;
}


private int mVolumeControlStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
public static final int USE_DEFAULT_STREAM_TYPE = Integer.MIN_VALUE;
//音量键松开
protected boolean onKeyUp(int featureId, int keyCode, KeyEvent event) {
final KeyEvent.DispatcherState dispatcher =
mDecor != null ? mDecor.getKeyDispatcherState() : null;
if (dispatcher != null) {
dispatcher.handleUpEvent(event);
}
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN: {
final int flags = AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE
| AudioManager.FLAG_FROM_KEY;
if (mMediaController != null) {
mMediaController.adjustVolume(0, flags);
} else {
MediaSessionLegacyHelper.getHelper(getContext()).sendAdjustVolumeBy(
mVolumeControlStreamType, 0, flags);
}
return true;
}
...
}


return false;
}


private MediaSessionManager mSessionManager;
public void sendAdjustVolumeBy(int suggestedStream, int delta, int flags) {
mSessionManager.dispatchAdjustVolume(suggestedStream, delta, flags);
if (DEBUG) {
Log.d(TAG, "dispatched volume adjustment");
}
}


private final ISessionManager mService;
public MediaSessionManager(Context context) {
mContext = context;
IBinder b = ServiceManager.getService(Context.MEDIA_SESSION_SERVICE);
mService = ISessionManager.Stub.asInterface(b);
}
//mservice为MediaSessionService对象
public void dispatchAdjustVolume(int suggestedStream, int direction, int flags) {
try {
mService.dispatchAdjustVolume(suggestedStream, direction, flags);
} catch (RemoteException e) {
Log.e(TAG, "Failed to send adjust volume.", e);
}
}






public void dispatchAdjustVolume(int suggestedStream, int delta, int flags) {
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
//获取MediaSessionRecord对象来控制音量
MediaSessionRecord session = mPriorityStack.getDefaultVolumeSession(mCurrentUserId);
dispatchAdjustVolumeLocked(suggestedStream, delta, flags, session);
}
} finally {
Binder.restoreCallingIdentity(token);
}
}


private IAudioService mAudioService;
 mAudioService = getAudioService();
 private IAudioService getAudioService() {
IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
return IAudioService.Stub.asInterface(b);
}
private void dispatchAdjustVolumeLocked(int suggestedStream, int direction, int flags,
MediaSessionRecord session) {
...
boolean preferSuggestedStream = false;
...
if (session == null || preferSuggestedStream) {
...
try {
//mAudioService实际上是AudioService的对象
String packageName = getContext().getOpPackageName();
mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream,
flags, packageName, TAG);
} catch (RemoteException e) {
Log.e(TAG, "Error adjusting default volume.", e);
}
}
...
}




private final ControllerService mControllerService = new ControllerService();
private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
String callingPackage, String caller, int uid) {
...
int streamType;
boolean isMute = isMuteAdjust(direction);
if (mVolumeControlStream != -1) {
streamType = mVolumeControlStream;
} else {
//将Integer.MIN_VALUE转换成streamType的形式,取值范围为0-10,表示音量值
streamType = getActiveStreamType(suggestedStreamType);
}
ensureValidStreamType(streamType);//数据正确性检查
final int resolvedStream = mStreamVolumeAlias[streamType];


//FLAG_PLAY_SOUND表示调整音量时播放声音
if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
resolvedStream != AudioSystem.STREAM_RING) {
flags &= ~AudioManager.FLAG_PLAY_SOUND;
}



if (mVolumeController.suppressAdjustment(resolvedStream, flags, isMute)) {
direction = 0;
flags &= ~AudioManager.FLAG_PLAY_SOUND;
flags &= ~AudioManager.FLAG_VIBRATE;//震动模式
if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
}
adjustStreamVolume(streamType, direction, flags, callingPackage, caller, uid);
}










 private void adjustStreamVolume(int streamType, int direction, int flags,
            String callingPackage, String caller, int uid) {
...
//数据正确性检查
ensureValidDirection(direction);
ensureValidStreamType(streamType);
boolean isMuteAdjust = isMuteAdjust(direction);
...
//获取streamType映射到的流类型
int streamTypeAlias = mStreamVolumeAlias[streamType];
//VolumeStreamState类,保存与一个流类型所有音量相关的信息
VolumeStreamState streamState = mStreamStates[streamTypeAlias];
//获取流类型所对应的音频设备
final int device = getDeviceForStream(streamTypeAlias);
//获取当前音量
int aliasIndex = streamState.getIndex(device);
boolean adjustVolume = true;
int step;
...
flags &= ~AudioManager.FLAG_FIXED_VOLUME;
if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
   ((device & mFixedVolumeDevices) != 0)) {
flags |= AudioManager.FLAG_FIXED_VOLUME;
...
} else {
//rescaleIndex用于将音量值的变化量从源流类型变换到目标流类型
//由于不同的流类型的音量调节范围不同,所以这个转换是必需的
step = rescaleIndex(10, streamType, streamTypeAlias);
}
...
//获取原始音量
int oldIndex = mStreamStates[streamType].getIndex(device);
//获取调整后的音量值
int newIndex = mStreamStates[streamType].getIndex(device);
...
int index = mStreamStates[streamType].getIndex(device);
//通知外接音量值发生变化
sendVolumeUpdate(streamType, oldIndex, index, flags);
}


private final VolumeController mVolumeController = new VolumeController();
private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
streamType = mStreamVolumeAlias[streamType];
if (streamType == AudioSystem.STREAM_MUSIC) {
flags = updateFlagsForSystemAudio(flags);
}
//将音量变化信息通知给SystemUI
mVolumeController.postVolumeChanged(streamType, flags);
}


private IVolumeController mController;
public void postVolumeChanged(int streamType, int flags) {
if (mController == null)
return;
try {
//mController为VolumeDialogController的实例
mController.volumeChanged(streamType, flags);
} catch (RemoteException e) {
Log.w(TAG, "Error calling volumeChanged", e);
}
}


public void volumeChanged(int streamType, int flags) throws RemoteException {
if (D.BUG) Log.d(TAG, "volumeChanged " + AudioSystem.streamToString(streamType)
+ " " + Util.audioManagerFlagsToString(flags));
if (mDestroyed) return;
//发送消息,mWork为VolumeDialogController的内部类W的实例
mWorker.obtainMessage(W.VOLUME_CHANGED, streamType, flags).sendToTarget();
}






@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case VOLUME_CHANGED: onVolumeChangedW(msg.arg1, msg.arg2); break;
...
}
}






private void onVolumeChangedW(int stream, int flags) {
final boolean showUI = (flags & AudioManager.FLAG_SHOW_UI) != 0;
final boolean fromKey = (flags & AudioManager.FLAG_FROM_KEY) != 0;
final boolean showVibrateHint = (flags & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0;
final boolean showSilentHint = (flags & AudioManager.FLAG_SHOW_SILENT_HINT) != 0;
boolean changed = false;
if (showUI) {
changed |= updateActiveStreamW(stream);
}
int lastAudibleStreamVolume = mAudio.getLastAudibleStreamVolume(stream);
changed |= updateStreamLevelW(stream, lastAudibleStreamVolume);
changed |= checkRoutedToBluetoothW(showUI ? AudioManager.STREAM_MUSIC : stream);
if (changed) {
mCallbacks.onStateChanged(mState);
}
if (showUI) {
mCallbacks.onShowRequested(Events.SHOW_REASON_VOLUME_CHANGED);
}
if (showVibrateHint) {
mCallbacks.onShowVibrateHint();
}
if (showSilentHint) {
mCallbacks.onShowSilentHint();
}
if (changed && fromKey) {
Events.writeEvent(mContext, Events.EVENT_KEY, stream, lastAudibleStreamVolume);
}
}




public void onStateChanged(final State state) {
final long time = System.currentTimeMillis();
final State copy = state.copy();
for (final Map.Entry<Callbacks, Handler> entry : mCallbackMap.entrySet()) {
entry.getValue().post(new Runnable() {
@Override
public void run() {
entry.getKey().onStateChanged(copy);
}
});
}
Events.writeState(time, copy);
}





















原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 荣耀v8手机开机键不灵怎么办 联通积分换的腾讯会员怎么办 小米6手机变卡了怎么办 微信绑定银行卡次数太多怎么办 银行卡绑定太多微信了怎么办 怎样给qq设密码怎么办 吃了心悦胶囊上火怎么办 qq暂时被冻结了怎么办 部落群审核未通过怎么办 qq被限制解封该怎么办 微信提现成功但没到账怎么办 拍拍贷登录不上怎么办 京东店铺出租保证金怎么办 所选地区无货怎么办 闲鱼七天没发货怎么办 续贷密码忘了怎么办 微店商家不发货怎么办 微店商家不退钱怎么办 维修车辆被拍违章停车怎么办 网贷申请平台太多怎么办 所在城市没有网店怎么办信用卡 拍拍贷不放款了怎么办 拍拍贷账号注销了怎么办 我在拍拍贷注销了怎么办 快贷逾期一年了怎么办 广州车牌买新车旧车怎么办 高尔夫旅行款被锁在车内怎么办 英雄联盟误删文件怎么办 拍拍贷换了号码怎么办 手机打开显示无法连接服务器怎么办 剑灵画面卡顿怎么办 cf被永久禁赛了怎么办 微信没有微游戏商店怎么办 游侠云盒下载慢怎么办2018 安卓手机玩网页游戏卡怎么办 safari点开什么都没有怎么办 康佳电视全网搜索打不开怎么办 脚被图钉扎了怎么办 电脑中毒了打不开软件怎么办 剑三程序不兼容怎么办 玩无主之地卡怎么办