首先播放音乐的时候,执行下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=falseWake 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.acquireWakeLock2. frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java       -->acquireWakeLock      -->acquireWakeLockInternal      -->updatePowerStateLocked      -->updateSuspendBlockerLocked      -->updatePowerStateLocked      -->updateSuspendBlockerLocked      -->mWakeLockSuspendBlocker.acquire     -->PowerManagerService$SuspendBlockerImpl.acquire-->nativeAcquireSuspendBlocker3. 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;    }

 

 

更多相关文章

  1. Java中的匿名内部类:由setOnClickListener说起
  2. 获取Android各类系统相关信息的接口实现代码
  3. Android 利用AudioManager控制后台音乐播放器暂停,播放
  4. 内部类联想到Android的Listener
  5. 基于Service与ContentProvider的音乐播放实例!
  6. Android Studio自动化快速实现Parcelable接口序列化
  7. Android 接口定义语言AIdl
  8. Android高仿网易云音乐播放界面
  9. android如何在xml中引用内部类

随机推荐

  1. Android(安卓)程序员指南 PDF下载
  2. Android(安卓)7.0新特性
  3. Gsensor的整个系统架构
  4. Android:系统信息(内存、cpu、sd卡、电量、
  5. 下载Android(安卓)5.0源码(附源码)
  6. Android获取点击屏幕的位置坐标
  7. Android(安卓)sqlite 数据库操作
  8. Android图片下载缓存库picasso解析
  9. android webview
  10. Android之SDK、NDK、JNI和so文件