抖音观看直播时,点击音量上键,无法调节音量

日志打印MediaSessionService相关信息:

10-07 19:11:28.967004  1578  3705 D MediaSessionService: dispatchVolumeKeyEvent, pkg=com.ss.android.ugc.aweme, opPkg=com.ss.android.ugc.aweme, pid=32083, uid=10219, asSystem=true, event=KeyEvent { action=ACTION_UP, keyCode=KEYCODE_VOLUME_UP, scanCode=115, metaState=0, flags=0x8, repeatCount=0, eventTime=369450945499000, downTime=369450256419000, deviceId=3, source=0x101, displayId=-1 }, stream=-2147483648, musicOnly=false
10-07 19:11:28.967339  1578  3705 D MediaSessionService: Adjusting suggestedStream=-2147483648 by 0. flags=4116, preferSuggestedStream=false, session=null

流程走到了 MediaSessionService.dispatchAdjustVolumeLocked() 方法内:

// system/frameworks/base/services/core/java/com/android/server/media/MediaSessionService.java
    private void dispatchAdjustVolumeLocked(String packageName, String opPackageName, int pid,
                int uid, boolean asSystemService, int suggestedStream, int direction, int flags,
                boolean musicOnly) {
            MediaSessionRecordImpl session = isGlobalPriorityActiveLocked() ? mGlobalPrioritySession
                    : mCurrentFullUserRecord.mPriorityStack.getDefaultVolumeSession();

            boolean preferSuggestedStream = false;
            if (isValidLocalStreamType(suggestedStream)
                    && AudioSystem.isStreamActive(suggestedStream, 0)) {
                preferSuggestedStream = true;
            }
            if (session == null || preferSuggestedStream) {
                if (DEBUG_KEY_EVENT) {
                    Log.d(TAG, "Adjusting suggestedStream=" + suggestedStream + " by " + direction
                            + ". flags=" + flags + ", preferSuggestedStream="
                            + preferSuggestedStream + ", session=" + session);
                }
                if (musicOnly && !AudioSystem.isStreamActive(AudioManager.STREAM_MUSIC, 0)) {
                    if (DEBUG_KEY_EVENT) {
                        Log.d(TAG, "Nothing is playing on the music stream. Skipping volume event,"
                                + " flags=" + flags);
                    }
                    return;
                }

                // Execute mAudioService.adjustSuggestedStreamVolume() on
                // handler thread of MediaSessionService.
                // This will release the MediaSessionService.mLock sooner and avoid
                // a potential deadlock between MediaSessionService.mLock and
                // ActivityManagerService lock.
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        final String callingOpPackageName;
                        final int callingUid;
                        final int callingPid;
                        if (asSystemService) {
                            callingOpPackageName = mContext.getOpPackageName();
                            callingUid = Process.myUid();
                            callingPid = Process.myPid();
                        } else {
                            callingOpPackageName = opPackageName;
                            callingUid = uid;
                            callingPid = pid;
                        }
                        try {
                            mAudioManager.adjustSuggestedStreamVolumeForUid(suggestedStream,
                                    direction, flags, callingOpPackageName, callingUid, callingPid,
                                    getContext().getApplicationInfo().targetSdkVersion);
                        } catch (SecurityException | IllegalArgumentException e) {
                            Log.e(TAG, "Cannot adjust volume: direction=" + direction
                                    + ", suggestedStream=" + suggestedStream + ", flags=" + flags
                                    + ", packageName=" + packageName + ", uid=" + uid
                                    + ", asSystemService=" + asSystemService, e);
                        }
                    }
                });
            } else {
                if (DEBUG_KEY_EVENT) {
                    Log.d(TAG, "Adjusting " + session + " by " + direction + ". flags="
                            + flags + ", suggestedStream=" + suggestedStream
                            + ", preferSuggestedStream=" + preferSuggestedStream);
                }
                session.adjustVolume(packageName, opPackageName, pid, uid, asSystemService,
                        direction, flags, true);
            }
        }

通过日志结合代码分析,调用 mAudioManager.adjustSuggestedStreamVolumeForUid 方法:

// system/frameworks/base/media/java/android/media/AudioManager.java
    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
    public void adjustSuggestedStreamVolumeForUid(int suggestedStreamType, int direction,
            @SystemVolumeFlags int flags,
            @NonNull String packageName, int uid, int pid, int targetSdkVersion) {
        try {
            getService().adjustSuggestedStreamVolumeForUid(suggestedStreamType, direction, flags,
                    packageName, uid, pid, UserHandle.getUserHandleForUid(uid), targetSdkVersion);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

 通过 AIDL 调用 AudioService.adjustSuggestedStreamVolumeForUid

// system/frameworks/base/services/core/java/com/android/server/audio/AudioService.java
    /** @see AudioManager#adjustSuggestedStreamVolumeForUid(int, int, int, String, int, int, int) */
    @Override
    public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags,
            @NonNull String packageName, int uid, int pid, UserHandle userHandle,
            int targetSdkVersion) {
        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
            throw new SecurityException("Should only be called from system process");
        }

        // direction and stream type swap here because the public
        // adjustSuggested has a different order than the other methods.
        adjustSuggestedStreamVolume(direction, streamType, flags, packageName, packageName,
                uid, pid, hasAudioSettingsPermission(uid, pid),
                AudioDeviceVolumeManager.ADJUST_MODE_NORMAL);
    }

最后调用到 AudioService.adjustSuggestedStreamVolume 方法,即从输入子系统进入到音频子系统。

由于该日志属于 CFC 版本,缺少AudioService日志,导致无法分析出问题发生时是否走到 adjustStreamVolume() 方法内部,该方法真正实现了系统对音量键事件触发的音量调整。

从代码上来看,必然会调用 adjustSuggestedStreamVolume() -> adjustStreamVolume()。

    /** All callers come from platform apps/system server, so no attribution tag is needed */
    private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
            String callingPackage, String caller, int uid, int pid, boolean hasModifyAudioSettings,
            int keyEventMode) {
        if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream=" + suggestedStreamType
                + ", flags=" + flags + ", caller=" + caller
                + ", volControlStream=" + mVolumeControlStream
                + ", userSelect=" + mUserSelectedVolumeControlStream);
        if (direction != AudioManager.ADJUST_SAME) {
            sVolumeLogger.enqueue(
                    new VolumeEvent(VolumeEvent.VOL_ADJUST_SUGG_VOL, suggestedStreamType,
                            direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
                            .append("/").append(caller).append(" uid:").append(uid).toString()));
        }

        boolean hasExternalVolumeController = notifyExternalVolumeController(direction);

        new MediaMetrics.Item(mMetricsId + "adjustSuggestedStreamVolume")
                .setUid(Binder.getCallingUid())
                .set(MediaMetrics.Property.CALLING_PACKAGE, callingPackage)
                .set(MediaMetrics.Property.CLIENT_NAME, caller)
                .set(MediaMetrics.Property.DIRECTION, direction > 0
                        ? MediaMetrics.Value.UP : MediaMetrics.Value.DOWN)
                .set(MediaMetrics.Property.EXTERNAL, hasExternalVolumeController
                        ? MediaMetrics.Value.YES : MediaMetrics.Value.NO)
                .set(MediaMetrics.Property.FLAGS, flags)
                .record();

        if (hasExternalVolumeController) {
            return;
        }

        final int streamType;
        synchronized (mForceControlStreamLock) {
            // Request lock in case mVolumeControlStream is changed by other thread.
            if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1
                streamType = mVolumeControlStream;
            } else {
                // TODO discard activity on a muted stream?
                final int maybeActiveStreamType = getActiveStreamType(suggestedStreamType);
                final boolean activeForReal;
                if (maybeActiveStreamType == AudioSystem.STREAM_RING
                        || maybeActiveStreamType == AudioSystem.STREAM_NOTIFICATION) {
                    activeForReal = wasStreamActiveRecently(maybeActiveStreamType, 0);
                } else {
                    activeForReal = mAudioSystem.isStreamActive(maybeActiveStreamType, 0);
                }
                if (activeForReal || mVolumeControlStream == -1) {
                    streamType = maybeActiveStreamType;
                } else {
                    streamType = mVolumeControlStream;
                }
            }
        }

        final boolean isMute = isMuteAdjust(direction);

        ensureValidStreamType(streamType);
        final int resolvedStream = mStreamVolumeAlias[streamType];

        // Play sounds on STREAM_RING only.
        if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
                resolvedStream != AudioSystem.STREAM_RING) {
            flags &= ~AudioManager.FLAG_PLAY_SOUND;
        }

        // For notifications/ring, show the ui before making any adjustments
        // Don't suppress mute/unmute requests
        // Don't suppress adjustments for single volume device
        if (mVolumeController.suppressAdjustment(resolvedStream, flags, isMute)
                && !mIsSingleVolume) {
            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, pid,
                null, hasModifyAudioSettings, keyEventMode);
    }

调用 adjustStreamVolume() 方法调整音量大小

    protected void adjustStreamVolume(int streamType, int direction, int flags,
            String callingPackage, String caller, int uid, int pid, String attributionTag,
            boolean hasModifyAudioSettings, int keyEventMode) {
        if (mUseFixedVolume) {
            return;
        }
        if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction
                + ", flags=" + flags + ", caller=" + caller);

        ensureValidDirection(direction);
        ensureValidStreamType(streamType);

        boolean isMuteAdjust = isMuteAdjust(direction);

        if (isMuteAdjust && !isStreamAffectedByMute(streamType)) {
            return;
        }

        // If adjust is mute and the stream is STREAM_VOICE_CALL or STREAM_BLUETOOTH_SCO, make sure
        // that the calling app have the MODIFY_PHONE_STATE permission.
        if (isMuteAdjust &&
            (streamType == AudioSystem.STREAM_VOICE_CALL ||
                streamType == AudioSystem.STREAM_BLUETOOTH_SCO) &&
                mContext.checkPermission(android.Manifest.permission.MODIFY_PHONE_STATE, pid, uid)
                    != PackageManager.PERMISSION_GRANTED) {
            Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: adjustStreamVolume from pid="
                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
            return;
        }

        // If the stream is STREAM_ASSISTANT,
        // make sure that the calling app have the MODIFY_AUDIO_ROUTING permission.
        if (streamType == AudioSystem.STREAM_ASSISTANT &&
                mContext.checkPermission(
                android.Manifest.permission.MODIFY_AUDIO_ROUTING, pid, uid)
                    != PackageManager.PERMISSION_GRANTED) {
            Log.w(TAG, "MODIFY_AUDIO_ROUTING Permission Denial: adjustStreamVolume from pid="
                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
            return;
        }

        // use stream type alias here so that streams with same alias have the same behavior,
        // including with regard to silent mode control (e.g the use of STREAM_RING below and in
        // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
        int streamTypeAlias = mStreamVolumeAlias[streamType];

        VolumeStreamState streamState = mStreamStates[streamTypeAlias];

        final int device = getDeviceForStream(streamTypeAlias);

        int aliasIndex = streamState.getIndex(device);
        boolean adjustVolume = true;
        int step;

        // skip a2dp absolute volume control request when the device
        // is neither an a2dp device nor BLE device
        if ((!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
                && !AudioSystem.DEVICE_OUT_ALL_BLE_SET.contains(device))
                && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
            return;
        }

        // If we are being called by the system (e.g. hardware keys) check for current user
        // so we handle user restrictions correctly.
        if (uid == android.os.Process.SYSTEM_UID) {
            uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
        }
        // validate calling package and app op
        if (!checkNoteAppOp(
                STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage, attributionTag)) {
            return;
        }

        mSoundDoseHelper.invalidatPendingVolumeCommand();

        flags &= ~AudioManager.FLAG_FIXED_VOLUME;
        if (streamTypeAlias == AudioSystem.STREAM_MUSIC && isFixedVolumeDevice(device)) {
            flags |= AudioManager.FLAG_FIXED_VOLUME;

            // Always toggle between max safe volume and 0 for fixed volume devices where safe
            // volume is enforced, and max and 0 for the others.
            // This is simulated by stepping by the full allowed volume range
            step = mSoundDoseHelper.getSafeMediaVolumeIndex(device);
            if (step < 0) {
                step = streamState.getMaxIndex();
            }
            if (aliasIndex != 0) {
                aliasIndex = step;
            }
        } else {
            // convert one UI step (+/-1) into a number of internal units on the stream alias
            step = rescaleStep(10, streamType, streamTypeAlias);
        }

        // If either the client forces allowing ringer modes for this adjustment,
        // or stream is used for UI sonification
        if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
                (isUiSoundsStreamType(streamTypeAlias))) {
            int ringerMode = getRingerModeInternal();
            // do not vibrate if already in vibrate mode
            if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
                flags &= ~AudioManager.FLAG_VIBRATE;
            }
            // Check if the ringer mode handles this adjustment. If it does we don't
            // need to adjust the volume further.
            final int result = checkForRingerModeChange(aliasIndex, direction, step,
                    streamState.mIsMuted, callingPackage, flags);
            adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
            // If suppressing a volume adjustment in silent mode, display the UI hint
            if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
                flags |= AudioManager.FLAG_SHOW_SILENT_HINT;
            }
            // If suppressing a volume down adjustment in vibrate mode, display the UI hint
            if ((result & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0) {
                flags |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
            }
        } else if (isStreamMutedByRingerOrZenMode(streamTypeAlias) && streamState.mIsMuted) {
            // if the stream is currently muted streams by ringer/zen mode
            // then it cannot be unmuted (without FLAG_ALLOW_RINGER_MODES) with an unmute or raise
            if (direction == AudioManager.ADJUST_TOGGLE_MUTE
                    || direction == AudioManager.ADJUST_UNMUTE
                    || direction == AudioManager.ADJUST_RAISE) {
                adjustVolume = false;
            }
        }

        // If the ringer mode or zen is muting the stream, do not change stream unless
        // it'll cause us to exit dnd
        if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
            adjustVolume = false;
        }
        int oldIndex = mStreamStates[streamType].getIndex(device);

        // Check if the volume adjustment should be handled by an absolute volume controller instead
        if (isAbsoluteVolumeDevice(device)
                && (flags & AudioManager.FLAG_ABSOLUTE_VOLUME) == 0) {
            AbsoluteVolumeDeviceInfo info = mAbsoluteVolumeDeviceInfoMap.get(device);
            if (info.mHandlesVolumeAdjustment) {
                dispatchAbsoluteVolumeAdjusted(streamType, info, oldIndex, direction,
                        keyEventMode);
                return;
            }
        }

        if (adjustVolume && (direction != AudioManager.ADJUST_SAME)
                && (keyEventMode != AudioDeviceVolumeManager.ADJUST_MODE_END)) {
            mAudioHandler.removeMessages(MSG_UNMUTE_STREAM);

            if (isMuteAdjust && !mFullVolumeDevices.contains(device)) {
                boolean state;
                if (direction == AudioManager.ADJUST_TOGGLE_MUTE) {
                    state = !streamState.mIsMuted;
                } else {
                    state = direction == AudioManager.ADJUST_MUTE;
                }
                muteAliasStreams(streamTypeAlias, state);
            } else if ((direction == AudioManager.ADJUST_RAISE)
                    && mSoundDoseHelper.raiseVolumeDisplaySafeMediaVolume(streamTypeAlias,
                            aliasIndex + step, device, flags)) {
                Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
            } else if (!isFullVolumeDevice(device)
                    && (streamState.adjustIndex(direction * step, device, caller,
                            hasModifyAudioSettings)
                            || streamState.mIsMuted)) {
                // Post message to set system volume (it in turn will post a
                // message to persist).
                if (streamState.mIsMuted) {
                    // Unmute the stream if it was previously muted
                    if (direction == AudioManager.ADJUST_RAISE) {
                        // unmute immediately for volume up
                        muteAliasStreams(streamTypeAlias, false);
                    } else if (direction == AudioManager.ADJUST_LOWER) {
                        if (mIsSingleVolume) {
                            sendMsg(mAudioHandler, MSG_UNMUTE_STREAM, SENDMSG_QUEUE,
                                    streamTypeAlias, flags, null, UNMUTE_STREAM_DELAY);
                        }
                    }
                }
                sendMsg(mAudioHandler,
                        MSG_SET_DEVICE_VOLUME,
                        SENDMSG_QUEUE,
                        device,
                        0,
                        streamState,
                        0);
            }

            int newIndex = mStreamStates[streamType].getIndex(device);

            // Check if volume update should be send to AVRCP
            if (streamTypeAlias == AudioSystem.STREAM_MUSIC
                    && AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
                    && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
                if (DEBUG_VOL) {
                    Log.d(TAG, "adjustSreamVolume: postSetAvrcpAbsoluteVolumeIndex index="
                            + newIndex + "stream=" + streamType);
                }
                mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(newIndex / 10);
            } else if (isAbsoluteVolumeDevice(device)
                    && (flags & AudioManager.FLAG_ABSOLUTE_VOLUME) == 0) {
                AbsoluteVolumeDeviceInfo info = mAbsoluteVolumeDeviceInfoMap.get(device);
                dispatchAbsoluteVolumeChanged(streamType, info, newIndex);
            }

            if (AudioSystem.isLeAudioDeviceType(device)
                    && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
                int nowStreamType = getBluetoothContextualVolumeStream();
                if (streamType == nowStreamType ||
                        (streamType == AudioSystem.STREAM_MUSIC
                                && nowStreamType == AudioSystem.STREAM_VOICE_CALL
                                && direction == AudioManager.ADJUST_UNMUTE)) {
                    streamType = nowStreamType;
                    newIndex = mStreamStates[streamType].getIndex(device);
                    if (DEBUG_VOL) {
                        Log.d(TAG, "adjustSreamVolume postSetLeAudioVolumeIndex index="
                                + newIndex + " stream=" + streamType);
                    }
                    mDeviceBroker.postSetLeAudioVolumeIndex(newIndex,
                            mStreamStates[streamType].getMaxIndex(), streamType);
                }
            }

            // Check if volume update should be send to Hearing Aid
            if (device == AudioSystem.DEVICE_OUT_HEARING_AID) {
                // only modify the hearing aid attenuation when the stream to modify matches
                // the one expected by the hearing aid
                if (streamType == getBluetoothContextualVolumeStream()) {
                    if (DEBUG_VOL) {
                        Log.d(TAG, "adjustSreamVolume postSetHearingAidVolumeIndex index="
                                + newIndex + " stream=" + streamType);
                    }
                    mDeviceBroker.postSetHearingAidVolumeIndex(newIndex, streamType);
                }
            }
        }

        final int newIndex = mStreamStates[streamType].getIndex(device);

        if (adjustVolume) {
            synchronized (mHdmiClientLock) {
                if (mHdmiManager != null) {
                    // At most one of mHdmiPlaybackClient and mHdmiTvClient should be non-null
                    HdmiClient fullVolumeHdmiClient = mHdmiPlaybackClient;
                    if (mHdmiTvClient != null) {
                        fullVolumeHdmiClient = mHdmiTvClient;
                    }

                    if (fullVolumeHdmiClient != null
                            && mHdmiCecVolumeControlEnabled
                            && streamTypeAlias == AudioSystem.STREAM_MUSIC
                            // vol change on a full volume device
                            && isFullVolumeDevice(device)) {
                        int keyCode = KeyEvent.KEYCODE_UNKNOWN;
                        switch (direction) {
                            case AudioManager.ADJUST_RAISE:
                                keyCode = KeyEvent.KEYCODE_VOLUME_UP;
                                break;
                            case AudioManager.ADJUST_LOWER:
                                keyCode = KeyEvent.KEYCODE_VOLUME_DOWN;
                                break;
                            case AudioManager.ADJUST_TOGGLE_MUTE:
                            case AudioManager.ADJUST_MUTE:
                            case AudioManager.ADJUST_UNMUTE:
                                // Many CEC devices only support toggle mute. Therefore, we send the
                                // same keycode for all three mute options.
                                keyCode = KeyEvent.KEYCODE_VOLUME_MUTE;
                                break;
                            default:
                                break;
                        }
                        if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
                            final long ident = Binder.clearCallingIdentity();
                            try {
                                switch (keyEventMode) {
                                    case AudioDeviceVolumeManager.ADJUST_MODE_NORMAL:
                                        fullVolumeHdmiClient.sendVolumeKeyEvent(keyCode, true);
                                        fullVolumeHdmiClient.sendVolumeKeyEvent(keyCode, false);
                                        break;
                                    case AudioDeviceVolumeManager.ADJUST_MODE_START:
                                        fullVolumeHdmiClient.sendVolumeKeyEvent(keyCode, true);
                                        break;
                                    case AudioDeviceVolumeManager.ADJUST_MODE_END:
                                        fullVolumeHdmiClient.sendVolumeKeyEvent(keyCode, false);
                                        break;
                                    default:
                                        Log.e(TAG, "Invalid keyEventMode " + keyEventMode);
                                }
                            } finally {
                                Binder.restoreCallingIdentity(ident);
                            }
                        }
                    }

                    if (streamTypeAlias == AudioSystem.STREAM_MUSIC
                            && (oldIndex != newIndex || isMuteAdjust)) {
                        maybeSendSystemAudioStatusCommand(isMuteAdjust);
                    }
                }
            }
        }
        sendVolumeUpdate(streamType, oldIndex, newIndex, flags, device);
        if (oldIndex != newIndex) {
            setRescaleStreamVolume(streamType, device, newIndex);
        }
    }

=============== 待更新 ===============

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值