Android13 AudioManager requestAudioFocus流程分析

首先看AudioManager的requestAudioFocus方法:

//frameworks/base/media/java/android/media/AudioManager.java
public class AudioManager {
    public int requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint) {
        PlayerBase.deprecateStreamTypeForPlayback(streamType,
                "AudioManager", "requestAudioFocus()");
        int status = AUDIOFOCUS_REQUEST_FAILED;


        try {
            // status is guaranteed to be either AUDIOFOCUS_REQUEST_FAILED or
            // AUDIOFOCUS_REQUEST_GRANTED as focus is requested without the
            // AUDIOFOCUS_FLAG_DELAY_OK flag
            status = requestAudioFocus(l,
                    new AudioAttributes.Builder()
                            .setInternalLegacyStreamType(streamType).build(),
                    durationHint,
                    0 /* flags, legacy behavior */); 调用requestAudioFocus的重载方法(4个参数)
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "Audio focus request denied due to ", e);
        }


        return status;
    }
}

调用requestAudioFocus的重载方法(4个参数):

//frameworks/base/media/java/android/media/AudioManager.java
public class AudioManager {
    public int requestAudioFocus(OnAudioFocusChangeListener l,
            @NonNull AudioAttributes requestAttributes,
            int durationHint,
            int flags) throws IllegalArgumentException {
        if (flags != (flags & AUDIOFOCUS_FLAGS_APPS)) {
            throw new IllegalArgumentException("Invalid flags 0x"
                    + Integer.toHexString(flags).toUpperCase());
        }
        return requestAudioFocus(l, requestAttributes, durationHint,
                flags & AUDIOFOCUS_FLAGS_APPS,
                null /* no AudioPolicy*/); //继续调用重载方法(5个参数)
    }
}

继续调用重载方法(5个参数):

//frameworks/base/media/java/android/media/AudioManager.java
public class AudioManager {
    public int requestAudioFocus(OnAudioFocusChangeListener l,
            @NonNull AudioAttributes requestAttributes,
            int durationHint,
            int flags,
            AudioPolicy ap) throws IllegalArgumentException {
        // parameter checking
        if (requestAttributes == null) {
            throw new IllegalArgumentException("Illegal null AudioAttributes argument");
        }
        if (!AudioFocusRequest.isValidFocusGain(durationHint)) {
            throw new IllegalArgumentException("Invalid duration hint");
        }
        if (flags != (flags & AUDIOFOCUS_FLAGS_SYSTEM)) {
            throw new IllegalArgumentException("Illegal flags 0x"
                + Integer.toHexString(flags).toUpperCase());
        }
        if (((flags & AUDIOFOCUS_FLAG_DELAY_OK) == AUDIOFOCUS_FLAG_DELAY_OK) && (l == null)) {
            throw new IllegalArgumentException(
                    "Illegal null focus listener when flagged as accepting delayed focus grant");
        }
        if (((flags & AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS)
                == AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) && (l == null)) {
            throw new IllegalArgumentException(
                    "Illegal null focus listener when flagged as pausing instead of ducking");
        }
        if (((flags & AUDIOFOCUS_FLAG_LOCK) == AUDIOFOCUS_FLAG_LOCK) && (ap == null)) {
            throw new IllegalArgumentException(
                    "Illegal null audio policy when locking audio focus");
        }


        final AudioFocusRequest afr = new AudioFocusRequest.Builder(durationHint)
                .setOnAudioFocusChangeListenerInt(l, null /* no Handler for this legacy API */)
                .setAudioAttributes(requestAttributes)
                .setAcceptsDelayedFocusGain((flags & AUDIOFOCUS_FLAG_DELAY_OK)
                        == AUDIOFOCUS_FLAG_DELAY_OK)
                .setWillPauseWhenDucked((flags & AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS)
                        == AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS)
                .setLocksFocus((flags & AUDIOFOCUS_FLAG_LOCK) == AUDIOFOCUS_FLAG_LOCK)
                .build(); //创建AudioFocusRequest对象,并设置参数
        return requestAudioFocus(afr, ap); //继续调用重载方法(2个参数)
    }
}

继续调用重载方法(2个参数):

//frameworks/base/media/java/android/media/AudioManager.java
public class AudioManager {
    public int requestAudioFocus(@NonNull AudioFocusRequest afr, @Nullable AudioPolicy ap) {
        if (afr == null) {
            throw new NullPointerException("Illegal null AudioFocusRequest");
        }
        // this can only be checked now, not during the creation of the AudioFocusRequest instance
        // 我们如果设置afr的locksFocus为ture时,需要指定ap,否则就抛异常,因为目前的版本lockfocus与audiopolicy是一起使用的因此这里做了这个判断
        if (afr.locksFocus() && ap == null) {
            throw new IllegalArgumentException(
                    "Illegal null audio policy when locking audio focus");
        }
        //(1)注册要在音频焦点更改时调用的侦听器,并跟踪关联的焦点请求(包括用于侦听器的处理程序)
        registerAudioFocusRequest(afr);
        final IAudioService service = getService();
        final int status;
        int sdk;
        try {
            sdk = getContext().getApplicationInfo().targetSdkVersion;
        } catch (NullPointerException e) {
            // some tests don't have a Context
            sdk = Build.VERSION.SDK_INT;
        }
        // (2)clientId 就是把我们传入的AudioFocusRequest里的listener转成了String
        final String clientId = getIdForAudioFocusListener(afr.getOnAudioFocusChangeListener());
        final BlockingFocusResultReceiver focusReceiver;
        synchronized (mFocusRequestsLock) {
            try {
                // TODO status contains result and generation counter for ext policy
                //(3) 调用到了AudioService中requestAudioFocus
                status = service.requestAudioFocus(afr.getAudioAttributes(),
                        afr.getFocusGain(), mICallBack,
                        mAudioFocusDispatcher,
                        clientId,
                        getContext().getOpPackageName() /* package name */, afr.getFlags(),
                        ap != null ? ap.cb() : null,
                        sdk);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
            // 上面说过了,目前Audio支持外部处理AudioFocus,这里判断如果不使用外部处理,则直接返回Android原生的申请焦点的结果。
            if (status != AudioManager.AUDIOFOCUS_REQUEST_WAITING_FOR_EXT_POLICY) {
                // default path with no external focus policy
                return status;
            }
            // 如果map为null,则new 1个size为1的map,这个主要也是处理外部音频焦点策略的
            if (mFocusRequestsAwaitingResult == null) {
                mFocusRequestsAwaitingResult =
                        new HashMap<String, BlockingFocusResultReceiver>(1);
            }
            //(4)关于音频焦点拿到外部处理这块不是一句两句说的明白的,后续在分析
            focusReceiver = new BlockingFocusResultReceiver(clientId);
            mFocusRequestsAwaitingResult.put(clientId, focusReceiver);
        }
        // 等待200ms 
        focusReceiver.waitForResult(EXT_FOCUS_POLICY_TIMEOUT_MS);
        if (DEBUG && !focusReceiver.receivedResult()) {
            Log.e(TAG, "requestAudio response from ext policy timed out, denying request");
        }
        synchronized (mFocusRequestsLock) {
            mFocusRequestsAwaitingResult.remove(clientId);
        }
        // 返回外部音频焦点处理结果
        return focusReceiver.requestResult();
    }
    ......
}

以上代码逻辑比较长,简单说下几个步骤:

  1. 参数的校验

  2. 注册要在音频焦点更改时调用的侦听器,并跟踪关联的焦点请求

  3. 调用AudioService的requestAudioFocus

  4. 判断是否有外部的audiopolicy,如果没有直接返回申请结果,如果有则等外外部音频焦点处理结果

registerAudioFocusRequest

其中步骤2的代码如下:

//frameworks/base/media/java/android/media/AudioManager.java
public class AudioManager {
    ......
    private final ConcurrentHashMap<String, FocusRequestInfo> mAudioFocusIdListenerMap =
            new ConcurrentHashMap<String, FocusRequestInfo>();
    ......
    private String getIdForAudioFocusListener(OnAudioFocusChangeListener l) {
        if (l == null) {
            return new String(this.toString());
        } else {
            return new String(this.toString() + l.toString());
        }
    }


    public void registerAudioFocusRequest(@NonNull AudioFocusRequest afr) {
        final Handler h = afr.getOnAudioFocusChangeListenerHandler(); //获取音频焦点变更监听器的Handler
        final FocusRequestInfo fri = new FocusRequestInfo(afr, (h == null) ? null :
            new ServiceEventHandlerDelegate(h).getHandler()); //创建音频焦点请求Info
        final String key = getIdForAudioFocusListener(afr.getOnAudioFocusChangeListener()); //获取监听器对应的key
        mAudioFocusIdListenerMap.put(key, fri); //将音频焦点请求Info和监听器对应的key放入HashMap
    }
    ......
}

AudioService.requestAudioFocus

其中步骤3的代码如下:

//frameworks/base/service/java/com/android/server/audio/AudioService.java
public class AudioService extends IAudioService.Stub
        implements AccessibilityManager.TouchExplorationStateChangeListener,
            AccessibilityManager.AccessibilityServicesStateChangeListener {
    ......
    private final MediaFocusControl mMediaFocusControl;
    ......
    public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb,
            IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
            IAudioPolicyCallback pcb, int sdk) {
        // permission checks
        if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) {
            if (AudioSystem.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) {
                if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
                            android.Manifest.permission.MODIFY_PHONE_STATE)) {
                    Log.e(TAG, "Invalid permission to (un)lock audio focus", new Exception());
                    return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
                }
            } else {
                // only a registered audio policy can be used to lock focus
                synchronized (mAudioPolicies) {
                    if (!mAudioPolicies.containsKey(pcb.asBinder())) {
                        Log.e(TAG, "Invalid unregistered AudioPolicy to (un)lock audio focus");
                        return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
                    }
                }
            }
        }


        if (callingPackageName == null || clientId == null || aa == null) {
            Log.e(TAG, "Invalid null parameter to request audio focus");
            return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
        }


        return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
                clientId, callingPackageName, flags, sdk,
                forceFocusDuckingForAccessibility(aa, durationHint, Binder.getCallingUid()));
    }
    ......
}

大体也是分了三步

  1. flag的检查,我们刚分析AudioManager的requestAudioFocus时已经看到了flag与audiopolicy的绑定判断,只不过到service又判断了一次,并详细说明了为何之前要绑定判断的原因,因为flag是lock的时候,如果不给电话用只能使用外部audiopolicy,所以之前要做与的判断。如果flag是lock状态并且给电话使用的话,那么我们就要使用requestAudioFocusForCall来申请。

  2. 参数判空的检查

  3. 调用了MediaFocusControl的requestAudioFocus

MediaFocusControl.requestAudioFocus

其中步骤3的代码如下:

public class MediaFocusControl implements PlayerFocusEnforcer {
    ......
    protected int requestAudioFocus(@NonNull AudioAttributes aa, int focusChangeHint, IBinder cb,
        IAudioFocusDispatcher fd, @NonNull String clientId, @NonNull String callingPackageName,
        int flags, int sdk, boolean forceDuck) {
        mEventLogger.log((new AudioEventLogger.StringEvent(
                "requestAudioFocus() from uid/pid " + Binder.getCallingUid()
                    + "/" + Binder.getCallingPid()
                    + " clientId=" + clientId + " callingPack=" + callingPackageName
                    + " req=" + focusChangeHint
                    + " flags=0x" + Integer.toHexString(flags)
                    + " sdk=" + sdk))
                .printLog(TAG));
        // we need a valid binder callback for clients
        if (!cb.pingBinder()) {
            Log.e(TAG, " AudioFocus DOA client for requestAudioFocus(), aborting.");
            return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
        }


        if (mAppOps.noteOp(AppOpsManager.OP_TAKE_AUDIO_FOCUS, Binder.getCallingUid(),
                callingPackageName) != AppOpsManager.MODE_ALLOWED) {
            return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
        }


        synchronized(mAudioFocusLock) {
          //其实申请成功的焦点都放到栈里维护起来了,那么这个焦点栈最多可存100个音频焦点的信息
            if (mFocusStack.size() > MAX_STACK_SIZE) {
                Log.e(TAG, "Max AudioFocus stack size reached, failing requestAudioFocus()");
                return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
            }


            boolean enteringRingOrCall = !mRingOrCallActive
                    & (AudioSystem.IN_VOICE_COMM_FOCUS_ID.compareTo(clientId) == 0);
            if (enteringRingOrCall) { mRingOrCallActive = true; }


            final AudioFocusInfo afiForExtPolicy;
            //假设我们不使用外部audiopolicy,只是用android原生的焦点策略,这个过
            if (mFocusPolicy != null) {
                // construct AudioFocusInfo as it will be communicated to audio focus policy
                afiForExtPolicy = new AudioFocusInfo(aa, Binder.getCallingUid(),
                        clientId, callingPackageName, focusChangeHint, 0 /*lossReceived*/,
                        flags, sdk);
            } else {
                afiForExtPolicy = null;
            }


            // handle delayed focus
            boolean focusGrantDelayed = false;
            // 如果当前是电话,我们申请的又不是一个可以delay的焦点,那么直接返回申请失败,如果申请的是delay的,则更新delay的flag为true
            if (!canReassignAudioFocus()) {
                if ((flags & AudioManager.AUDIOFOCUS_FLAG_DELAY_OK) == 0) {
                    return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
                } else {
                    // request has AUDIOFOCUS_FLAG_DELAY_OK: focus can't be
                    // granted right now, so the requester will be inserted in the focus stack
                    // to receive focus later
                    focusGrantDelayed = true;
                }
            }


            // external focus policy? 
            if (mFocusPolicy != null) {
                if (notifyExtFocusPolicyFocusRequest_syncAf(afiForExtPolicy, fd, cb)) { //如果是外部音频焦点策略,通过AudioPolicy.AudioPolicyFocusListener调用到CarZonesAudioFocus
                    // stop handling focus request here as it is handled by external audio
                    // focus policy (return code will be handled in AudioManager)
                    return AudioManager.AUDIOFOCUS_REQUEST_WAITING_FOR_EXT_POLICY;
                } else {
                    // an error occured, client already dead, bail early
                    return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
                }
            }


            // handle the potential premature death of the new holder of the focus
            // (premature death == death before abandoning focus)
            // Register for client death notification
            AudioFocusDeathHandler afdh = new AudioFocusDeathHandler(cb);


            try {
                cb.linkToDeath(afdh, 0);
            } catch (RemoteException e) {
                // client has already died!
                Log.w(TAG, "AudioFocus  requestAudioFocus() could not link to "+cb+" binder death");
                return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
            }
           // 如果申请的音频焦点已经在栈顶存在,则直接返回成功
            if (!mFocusStack.empty() && mFocusStack.peek().hasSameClient(clientId)) {
                // if focus is already owned by this client and the reason for acquiring the focus
                // hasn't changed, don't do anything
                final FocusRequester fr = mFocusStack.peek();
                if (fr.getGainRequest() == focusChangeHint && fr.getGrantFlags() == flags) {
                    // unlink death handler so it can be gc'ed.
                    // linkToDeath() creates a JNI global reference preventing collection.
                    cb.unlinkToDeath(afdh, 0);
                    notifyExtPolicyFocusGrant_syncAf(fr.toAudioFocusInfo(),
                            AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
                    return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
                }
                // the reason for the audio focus request has changed: remove the current top of
                // stack and respond as if we had a new focus owner
                // 如果焦点栈中有此焦点的clientid,又不是delay状态,则移除栈中的这个焦点信息,
                // 这部分可以简单理解为用一个listener申请了两次不同的焦点,则会移除第一次申请的焦点信息
                if (!focusGrantDelayed) {
                    mFocusStack.pop();
                    // the entry that was "popped" is the same that was "peeked" above
                    fr.release();
                }
            }


            // focus requester might already be somewhere below in the stack, remove it
            removeFocusStackEntry(clientId, false /* signal */, false /*notifyFocusFollowers*/);


            final FocusRequester nfr = new FocusRequester(aa, focusChangeHint, flags, fd, cb,
                    clientId, afdh, callingPackageName, Binder.getCallingUid(), this, sdk); //创建音频焦点请求者
            if (focusGrantDelayed) {
                // focusGrantDelayed being true implies we can't reassign focus right now
                // which implies the focus stack is not empty.
                //对于申请delay的焦点直接放入栈中被delay的焦点下面,比如当前栈中的焦点是电话,那么我们申请的这个允许delay的焦点就放到电话的下面
                final int requestResult = pushBelowLockedFocusOwners(nfr);
                if (requestResult != AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
                    notifyExtPolicyFocusGrant_syncAf(nfr.toAudioFocusInfo(), requestResult);
                }
                return requestResult;
            } else {
                // propagate the focus change through the stack
                //处理不是delay的焦点的情况 遍历焦点栈中所有焦点与之仲裁(主要是给处理栈中已有焦点对应的listener),并将此次申请的音频焦点放入栈中
                if (!mFocusStack.empty()) {
                    propagateFocusLossFromGain_syncAf(focusChangeHint, nfr, forceDuck);
                }


                // push focus requester at the top of the audio focus stack
                mFocusStack.push(nfr);
                nfr.handleFocusGainFromRequest(AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
            }
            notifyExtPolicyFocusGrant_syncAf(nfr.toAudioFocusInfo(),
                    AudioManager.AUDIOFOCUS_REQUEST_GRANTED);


            if (ENFORCE_MUTING_FOR_RING_OR_CALL & enteringRingOrCall) {
                runAudioCheckerForRingOrCallAsync(true/*enteringRingOrCall*/);
            }
        }//synchronized(mAudioFocusLock)


        return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
    }
    ......
}
notifyExtFocusPolicyFocusRequest_syncAf

调用notifyExtFocusPolicyFocusRequest_syncAf方法,进行外部焦点请求处理:

//frameworks/base/service/java/com/android/server/audio/MediaFocusControl.java
public class MediaFocusControl implements PlayerFocusEnforcer {
    @Nullable private IAudioPolicyCallback mFocusPolicy = null;
    boolean notifyExtFocusPolicyFocusRequest_syncAf(AudioFocusInfo afi,
            IAudioFocusDispatcher fd, @NonNull IBinder cb) {
        if (DEBUG) {
            Log.v(TAG, "notifyExtFocusPolicyFocusRequest client="+afi.getClientId()
            + " dispatcher=" + fd);
        }
        synchronized (mExtFocusChangeLock) {
            afi.setGen(mExtFocusChangeCounter++);
        }
        final FocusRequester existingFr = mFocusOwnersForFocusPolicy.get(afi.getClientId());
        boolean keepTrack = false;
        if (existingFr != null) {
            if (!existingFr.hasSameDispatcher(fd)) {
                existingFr.release();
                keepTrack = true;
            }
        } else {
            keepTrack = true;
        }
        if (keepTrack) {
            final AudioFocusDeathHandler hdlr = new AudioFocusDeathHandler(cb);
            try {
                cb.linkToDeath(hdlr, 0);
            } catch (RemoteException e) {
                // client has already died!
                return false;
            }
            // new focus (future) focus owner to keep track of
            mFocusOwnersForFocusPolicy.put(afi.getClientId(),
                    new FocusRequester(afi, fd, cb, hdlr, this));
        }


        try {
            //oneway
            mFocusPolicy.notifyAudioFocusRequest(afi, AudioManager.AUDIOFOCUS_REQUEST_GRANTED); //调用IAudioPolicyCallback的notifyAudioFocusRequest方法
            return true;
        } catch (RemoteException e) {
            Log.e(TAG, "Can't call notifyAudioFocusRequest() on IAudioPolicyCallback "
                    + mFocusPolicy.asBinder(), e);
        }
        return false;
    }
}

IAudioPolicyCallback的notifyAudioFocusRequest方法,IAudioPolicyCallback是一个接口,其实现在AudioPolicy中:

//frameworks/base/media/java/android/media/audiopolicy/AudioPolicy.java      
public class AudioPolicy {
    private final IAudioPolicyCallback mPolicyCb = new IAudioPolicyCallback.Stub() {


        public void notifyAudioFocusGrant(AudioFocusInfo afi, int requestResult) {
            sendMsg(MSG_FOCUS_GRANT, afi, requestResult);
            if (DEBUG) {
                Log.v(TAG, "notifyAudioFocusGrant: pack=" + afi.getPackageName() + " client="
                        + afi.getClientId() + "reqRes=" + requestResult);
            }
        }


        public void notifyAudioFocusLoss(AudioFocusInfo afi, boolean wasNotified) {
            sendMsg(MSG_FOCUS_LOSS, afi, wasNotified ? 1 : 0);
            if (DEBUG) {
                Log.v(TAG, "notifyAudioFocusLoss: pack=" + afi.getPackageName() + " client="
                        + afi.getClientId() + "wasNotified=" + wasNotified);
            }
        }


        public void notifyAudioFocusRequest(AudioFocusInfo afi, int requestResult) {
            sendMsg(MSG_FOCUS_REQUEST, afi, requestResult); //发送MSG_FOCUS_REQUEST消息
            if (DEBUG) {
                Log.v(TAG, "notifyAudioFocusRequest: pack=" + afi.getPackageName() + " client="
                        + afi.getClientId() + " gen=" + afi.getGen());
            }
        }


        public void notifyAudioFocusAbandon(AudioFocusInfo afi) {
            sendMsg(MSG_FOCUS_ABANDON, afi, 0 /* ignored */);
            if (DEBUG) {
                Log.v(TAG, "notifyAudioFocusAbandon: pack=" + afi.getPackageName() + " client="
                        + afi.getClientId());
            }
        }


        public void notifyMixStateUpdate(String regId, int state) {
            for (AudioMix mix : mConfig.getMixes()) {
                if (mix.getRegistration().equals(regId)) {
                    mix.mMixState = state;
                    sendMsg(MSG_MIX_STATE_UPDATE, mix, 0/*ignored*/);
                    if (DEBUG) {
                        Log.v(TAG, "notifyMixStateUpdate: regId=" + regId + " state=" + state);
                    }
                }
            }
        }


        public void notifyVolumeAdjust(int adjustment) {
            sendMsg(MSG_VOL_ADJUST, null /* ignored */, adjustment);
            if (DEBUG) {
                Log.v(TAG, "notifyVolumeAdjust: " + adjustment);
            }
        }


        public void notifyUnregistration() {
            setRegistration(null);
        }
    }
}

发送MSG_FOCUS_REQUEST消息,在EventHandler中会处理这个消息:

//frameworks/base/media/java/android/media/audiopolicy/AudioPolicy.java      
public class AudioPolicy {
    private AudioPolicyFocusListener mFocusListener;
    private class EventHandler extends Handler {
        public EventHandler(AudioPolicy ap, Looper looper) {
            super(looper);
        }


        @Override
        public void handleMessage(Message msg) {
            switch(msg.what) {
                case MSG_POLICY_STATUS_CHANGE:
                    onPolicyStatusChange();
                    break;
                case MSG_FOCUS_GRANT:
                    if (mFocusListener != null) {
                        mFocusListener.onAudioFocusGrant(
                                (AudioFocusInfo) msg.obj, msg.arg1);
                    }
                    break;
                case MSG_FOCUS_LOSS:
                    if (mFocusListener != null) {
                        mFocusListener.onAudioFocusLoss(
                                (AudioFocusInfo) msg.obj, msg.arg1 != 0);
                    }
                    break;
                case MSG_MIX_STATE_UPDATE:
                    if (mStatusListener != null) {
                        mStatusListener.onMixStateUpdate((AudioMix) msg.obj);
                    }
                    break;
                case MSG_FOCUS_REQUEST:
                    if (mFocusListener != null) {
                        mFocusListener.onAudioFocusRequest((AudioFocusInfo) msg.obj, msg.arg1);
                    } else { // should never be null, but don't crash
                        Log.e(TAG, "Invalid null focus listener for focus request event");
                    }
                    break;
                case MSG_FOCUS_ABANDON:
                    if (mFocusListener != null) { // should never be null
                        mFocusListener.onAudioFocusAbandon((AudioFocusInfo) msg.obj);
                    } else { // should never be null, but don't crash
                        Log.e(TAG, "Invalid null focus listener for focus abandon event");
                    }
                    break;
                case MSG_VOL_ADJUST:
                    if (mVolCb != null) {
                        mVolCb.onVolumeAdjustment(msg.arg1);
                    } else { // should never be null, but don't crash
                        Log.e(TAG, "Invalid null volume event");
                    }
                    break;
                default:
                    Log.e(TAG, "Unknown event " + msg.what);
            }
        }
    }
}

调用AudioPolicyFocusListener的onAudioFocusRequest方法,AudioPolicyFocusListener是一个接口,由CarZonesAudioFocus实现,因此会调用CarZonesAudioFocus的onAudioFocusRequest方法:

待更新

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值