Android 判断app是否正在播放音乐

首先播放音乐的时候,执行下adb命令:

adb shell dumpsys power|grep -i wake

以播放网易云音乐为例:

C:\Users\Administrator>adb shell dumpsys power| findstr -i wake
    no_cached_wake_locks=true
  mWakefulness=Awake
  mWakefulnessChanging=false
  mWakeLockSummary=0x1
  mLastWakeTime=187182227 (24697 ms ago)
  mHoldingWakeLockSuspendBlocker=true
  mWakeUpWhenPluggedOrUnpluggedConfig=true
  mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig=false
  mDrawWakeLockOverrideFromSidekick=false
  mDoubleTapWakeEnabled=false
Wake Locks: size=2
  PARTIAL_WAKE_LOCK              'AudioMixAudioOut_D' ACQ=-831ms (uid=1041 ws=WorkSource{10139})
  PARTIAL_WAKE_LOCK              'com.netease.cloudmusic.module.player.NeteaseAudioPlayer' ON_AFTER_RELEASE ACQ=-1s168ms (uid=10139 pid=26062)
  PowerManagerService.WakeLocks: ref count=1

wakeLock的tag标志是‘’AudioMixAudioOut_D‘’,我们就可以通过这个tag来判断是不是音乐类的应用,那怎么判断是否正在播放音乐呢,下面开始分析

framewroks\base\core\java\android\os\PowerManagerInternal.java有个内部接口PowerControllerInternalCallback

    public interface PowerControllerInternalCallback {
        public void onWakeLockAcquired(String tag, String packageName,
                int ownerUid, int ownerPid, WorkSource workSource);

        public void onWakeLockReleased(String tag, String packageName,
                int ownerUid, int ownerPid, WorkSource workSource);

        public void onWakeLockChanging(String tag, String packageName,
                int ownerUid, int ownerPid, WorkSource workSource, String newTag,
                String newPackageName, int newOwnerUid, int newOwnerPid, WorkSource newWorkSource);

        public void onConstraintAppAcquireWakeLock(long nowElapsed, long wakelockStartTime);
    }

已展讯省电功能为例:

首先实现PowerControllerInternalCallback接口:

frameworks\base\services\core\java\com\android\server\power\sprdpower\WakelockConstraintHelper.java

    private class WakeLockObserver
        implements PowerManagerInternal.PowerControllerInternalCallback {
        @Override
        public void onWakeLockAcquired(String tag, String packageName,
            int ownerUid, int ownerPid, WorkSource workSource) {
            noteAudioWakeLockAcquired(tag, packageName, ownerUid, ownerPid, workSource);
        }
        @Override
        public void onWakeLockReleased(String tag, String packageName,
            int ownerUid, int ownerPid, WorkSource workSource) {
            noteAudioWakeLockReleased(tag, packageName, ownerUid, ownerPid, workSource);
        }
        @Override
        public void onWakeLockChanging(String tag, String packageName,
                int ownerUid, int ownerPid, WorkSource workSource,String newTag,
                String newPackageName, int newOwnerUid, int newOwnerPid, WorkSource newWorkSource) {
            noteAudioWakeLockChanging(tag, packageName,
                ownerUid, ownerPid, workSource, newTag,
                newPackageName, newOwnerUid, newOwnerPid, newWorkSource);
        }
        @Override
        public void onConstraintAppAcquireWakeLock(long nowElapsed, long wakelockStartTime) {
            noteConstraintAppAcquireWakeLock(nowElapsed, wakelockStartTime);
        }
    }

再将这个WakeLockObserver注册到PowerManagerInternal

mLocalPowerManager = LocalServices.getService(PowerManagerInternal.class);
......
mLocalPowerManager.registerPowerControllerInternalCallback(mWakeLockObserver);

PowerManagerInternal.java是个抽象类,在PowerManagerService.java中的内部类LocalService继承了PowerManagerInternal

这样当系统监听到有wakelock申请就会调用onWakeLockAcquired()方法

app层acquire WakeLock的大致流程如下:

1. frameworks/base/core/java/android/os/PowerManager.java
        acquire--->acquireLocked---->PowerManagerService.acquireWakeLock

2. frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

       -->acquireWakeLock

      -->acquireWakeLockInternal

      -->updatePowerStateLocked

      -->updateSuspendBlockerLocked

      -->updatePowerStateLocked

      -->updateSuspendBlockerLocked

      -->mWakeLockSuspendBlocker.acquire

     -->PowerManagerService$SuspendBlockerImpl.acquire-->nativeAcquireSuspendBlocker

3. frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp

      nativeAcquireSuspendBlocker-->acquire_wake_lock

回归我们的主题

PowerManagerService.java-->acquireWakeLockInternal()就会调用我们需要的方法notifyWakeLockAcquiredLocked()

    private void notifyWakeLockAcquiredLocked(WakeLock wakeLock) {
        if (mSystemReady && !wakeLock.mDisabled) {
            wakeLock.mNotifiedAcquired = true;
            mNotifier.onWakeLockAcquired(wakeLock.mFlags, wakeLock.mTag, wakeLock.mPackageName,
                    wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource,
                    wakeLock.mHistoryTag);
            restartNofifyLongTimerLocked(wakeLock);

            // NOTE: Bug #627645 low power Feature BEG-->
            // notify listeners
            mPowerControllerHelper.notifyWakeLockAcquiredLocked(wakeLock);
            // <-- NOTE: Bug #627645 low power Feature END
        }
    }

PowerControllerHelper是展讯在PowerManagerService.java增加的一个内部类

PowerControllerHelper-->notifyWakeLockAcquiredLocked()

        public void notifyWakeLockAcquiredLocked(WakeLock wakeLock) {
            if (wakeLock.mStartAcquireTimeStamp <= 0) {
                wakeLock.mStartAcquireTimeStamp = SystemClock.elapsedRealtime();
            } else {
                Slog.d(TAG, "call notifyWakeLockAcquiredLocked > 1, wake lock:" + wakeLock.mTag
                    + " from " + wakeLock.mPackageName + "(" + wakeLock.mOwnerUid +")");
            }

            // if Audio acquired a wakelock notify listeners
            if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) == PowerManager.PARTIAL_WAKE_LOCK
                && Process.AUDIOSERVER_UID == wakeLock.mOwnerUid) {
                if (mPowerControllerInternalCallback != null) {
                    mPowerControllerInternalCallback.onWakeLockAcquired(wakeLock.mTag, wakeLock.mPackageName,
                        wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource);
                }
            }
        }

在这里判断锁的level等级是PARTIAL_WAKE_LOCK,再判断进程uid是不是AUDIOSERVER_UID

    /**
     * Defines the UID/GID for the audioserver process.
     * @hide
     */
    public static final int AUDIOSERVER_UID = 1041;

先补充说明下WakeLock levelAndFlags和使用场景

Android 判断app是否正在播放音乐_第1张图片

除了这四个Level之外,PowerMager还提供了两个Flag,可以配合Level使用。

Android 判断app是否正在播放音乐_第2张图片

现在再回过头看notifyWakeLockAcquiredLocked(),如果满足PARTIAL_WAKE_LOCK和AUDIOSERVER_UID的判断条件就会调用我们上面说的接口PowerControllerInternalCallback里的onWakeLockAcquired()方法了

现在就走进了WakelockConstraintHelper.java的onWakeLockAcquired()中

        public void onWakeLockAcquired(String tag, String packageName,
            int ownerUid, int ownerPid, WorkSource workSource) {
            noteAudioWakeLockAcquired(tag, packageName, ownerUid, ownerPid, workSource);
        }
    private void noteAudioWakeLockAcquired(String tag, String packageName,
        int ownerUid, int ownerPid, WorkSource workSource) {

        if (DEBUG) Slog.d(TAG, "noteAudioWakeLockAcquired: workSource:" + workSource);

        // only care about the workSource
        if (workSource == null) return;
        if (!AUDIO_PACKAGE_NAME.equals(packageName) || Process.AUDIOSERVER_UID != ownerUid) return;

        //try {
            ArrayList uids = new ArrayList();

            if (workSource != null) {
                int num = workSource.size();
                int count = 0;
                for (; count
            case MSG_AUDIOOUT_WAKELOCK_UPDATED:
                handleAudioOutWakeLockUpdated((WakeLockInfo)msg.obj);
                break;
private void handleAudioOutWakeLockUpdated(WakeLockInfo wakeLockInfo) {
    ......
    appState.updateAudioState(audioFlag);
    ......
}

 

    public void updateAudioState(int audioState) {
        if (mAudioFlag != audioState
            && (audioState & AUDIO_TYPE_OUT) != 0) {
            mLastTimePlayingMusicSeen = SystemClock.elapsedRealtime();
        }

        mAudioFlag = audioState;
    }

 

    public boolean isPlayingMusic() {
        return (mAudioFlag & AUDIO_TYPE_OUT) != 0;
    }

当需要判断是否在播放音乐的时候,就会结合这个mAudioFlag和AudioManager的isMusicActive()来判断是否正在播放音乐

    private boolean isPlayingMusicInternal(AppState appState) {
        if (appState.mPlayingMusic) return true;

        if(mAudioManager != null && !mAudioManager.isMusicActive()
            /*&& !mAudioManager.isFmActive()*/){
            return false;
        }

        if (DEBUG_MORE) Slog.d(TAG, "mAudioManager.isMusicActive(): " + mAudioManager.isMusicActive()
            + " getMode():" + mAudioManager.getMode());

        boolean playing = appState.isPlayingMusic();

        // if app is still playing music after system standby for APP_PLAYING_MUSIC_THRESHOLD
        // set app to be playing music
        if (playing && mStandbyStartTime > 0) {
            long standbyDuration = SystemClock.elapsedRealtime() - mStandbyStartTime;
            if (standbyDuration > APP_PLAYING_MUSIC_THRESHOLD)
                appState.setPlayingMusicState(true);
        }

        return playing;
    }

 

 

你可能感兴趣的:(Android,省电管理)