Android6.0 - PowerManagerService Notifier 分析

개발 조회 수 705 추천 수 0 2017.07.21 15:20:39

Android6.0 - PowerManagerService Notifier 分析(분석)
   http://www.voidcn.com/blog/kc58236582/article/p-6003357.html


  这个类(Lèi)在PowerManagerService中是非常重要的,当PowerManagerService的状态改变(Gǎibiàn)时,都是靠(Kào)这个类通知(Tōngzhī).
  比如常用的灭屏和亮屏广播(Guǎngbò),也是在这个类中发送(Fāsòng)的.
  이 방법은 PowerManagerService 중에서 가장 중요하며, PowerManagerService의 상태 변화시, 모두 이 방법으로(靠) 통지한다.
  예를 들어 보통의 LCD 꺼짐과 LCD 켜짐을 알린다(broadcast), 또 이 방법으로 발송한다.
 
一、Notifier初始化(chūshǐhuà), Initialize

  首先我们来看它在PowerManagerService构造函数中(Gòuzào hánshù zhōng)的初始化:
  먼저 우리는 PowerManagerService의 구조체(함수중) 초기화를 보자.


   mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
     mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"), mPolicy);


  PowerManagerService把自己的main looper传进去了,说明在Notifier的消息处理是在PowerManagerService的主线程中,还有一点和之前的WakeLocks,和Display锁一样,这里也为Notifier创建了一个Broadcasts锁。
  PowerManagerService는 자기의 main looper로 진입하고, 설명(说明)notifier의 메시지처리(消息处理)는 PowerManagerService의 메인스레드(主线程中)에 있고,  또 약간 그리고 이전의 WakeLocks 와 Display Lock(잠금,锁)과 같은 것을 갖고 있고, 여기 또 Notifier 을 위해서 1개 Broadcats Lock(잠금,锁)을 생성한다(创建).


二、持锁(Chí suǒ), Lock
  我们现在开始看各PowerManagerService个状态(zhuàngtài)是如何(rúhé)在Notifier里处理(chǔlǐ )的。先来看acquireWakeLockInternal函数(hánshù)
  우리는 각 PowerManagerService 상태가 Notifier에서 어떻게 처리가 되는 지를 보자. 먼저 acquireWakeLockInternal 함수를 보면.
   private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName, WorkSource ws, String historyTag, int uid, int pid) {
    synchronized (mLock) {
     WakeLock wakeLock;
     int index = findWakeLockIndexLocked(lock);
     boolean notifyAcquire;
     if (index >= 0) {
      wakeLock = mWakeLocks.get(index);
      if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {
       // Update existing wake lock.  This shouldn't happen but is harmless.
       notifyWakeLockChangingLocked(wakeLock, flags, tag, packageName,
         uid, pid, ws, historyTag);
       wakeLock.updateProperties(flags, tag, packageName, ws, historyTag, uid, pid);
      }
      notifyAcquire = false;
     } else {
      wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid);
      try {
       lock.linkToDeath(wakeLock, 0);
      } catch (RemoteException ex) {
       throw new IllegalArgumentException("Wake lock is already dead.");
      }
      mWakeLocks.add(wakeLock);
      setWakeLockDisabledStateLocked(wakeLock);
      notifyAcquire = true; // 只有在新建(Xīnjiàn)的时候通知Notifier
     }

     applyWakeLockFlagsOnAcquireLocked(wakeLock, uid);
     mDirty |= DIRTY_WAKE_LOCKS;
     updatePowerStateLocked();
     if (notifyAcquire) {
      // This needs to be done last so we are sure we have acquired the
      // kernel wake lock.  Otherwise we have a race where the system may
      // go to sleep between the time we start the accounting in battery
      // stats and when we actually get around to telling the kernel to
      // stay awake.
      notifyWakeLockAcquiredLocked(wakeLock);
     }
    }
   }
  
  我们看上面函数只有在WakeLock是新建的时候才(cái)会调用(diàoyòng)notifyWakeLockAcquiredLocked函数
  우리는 볼수 있다, 오직 WakeLock은 새로운 시간에 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);
    }
   }

  

Notifier也是统计(tǒngjì)电量(diànliàng)和appops处理(chǔlǐ)下。 
 Notifier는 또한 统计电量(통계전기량, 전력소비량 통계)과 appops 처리를 아래 같이 한다. Notifier is also the statistical power and appops processing.

   public void onWakeLockAcquired(int flags, String tag, String packageName, int ownerUid, int ownerPid, WorkSource workSource, String historyTag) {
    final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
    if (monitorType >= 0) {
     try {
      final boolean unimportantForLogging = ownerUid == Process.SYSTEM_UID
        && (flags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0;
      if (workSource != null) {
       mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag,
         historyTag, monitorType, unimportantForLogging);
      } else {
       mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, historyTag,
         monitorType, unimportantForLogging);
       // XXX need to deal with disabled operations.
       mAppOps.startOperation(AppOpsManager.getToken(mAppOps),
         AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName);
      }
     } catch (RemoteException ex) {
      // Ignore
     }
    }
   }


 PowerManagerService在删除锁(shānchú suǒ)的时候会调用(Diàoyòng)mNotifier.onWakeLockReleased函数,更新锁(gēng xīn suǒ)的时候最后会调用mNotifier.onWakeLockChanging函数。
  PowerManagerService는 locked 될 때 mNotifier.onWakeLockReleased 함수를 호출하고,  Lock이 갱신 될때 마지막의 Notifier.onWakeLockChanging 함수를 호출한다.
  这里面都是通知电池以及appops相关。 여기서 모두 통지한다, 배터리 및 appops 관련된 것들을.


三、唤醒(huànxǐng), Wake
  在PowerManagerService的wakeUpNoUpdateLocked函数会调用如下函数. 다음과 같이 함수를 호출 할 수 있다.
   mNotifier.onWakeUp(reason, reasonUid, opPackageName, opUid);
 
  再看(next)下Notifier处理(Chǔlǐ) 처리:
   public void onWakeUp(String reason, int reasonUid, String opPackageName, int opUid) {
    try {
     mBatteryStats.noteWakeUp(reason, reasonUid);
     if (opPackageName != null) {
      mAppOps.noteOperation(AppOpsManager.OP_TURN_SCREEN_ON, opUid, opPackageName);
     }
    } catch (RemoteException ex) {
     // Ignore
    }

   }


四、userActivity
  在userActivityNoUpdateLocked函数中也会调用如下函数. userActivityNoUpdateLocked 함수에서 또한 다음과 같은 함수를 호출 할 수 있다.
   mNotifier.onUserActivity(event, uid);

  我们看下Notifier的处理
   public void onUserActivity(int event, int uid) {
    try {
     mBatteryStats.noteUserActivity(uid, event);
    } catch (RemoteException ex) {
     // Ignore
    }

    synchronized (mLock) {
     if (!mUserActivityPending) {
      mUserActivityPending = true;
      Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY);
      msg.setAsynchronous(true);
      mHandler.sendMessage(msg);
     }
    }
   }
  
  消息(Xiāo xí)处理函数为 : sendUserActivity  

  메세지 처리 함수는(为 = 是)

  最后是在PhoneWindowManager中处理好像(hǎoxiàng)是在keyguard中处理。 (好像 : 마치 ~와 같이 하다)
  마지막으로 PhoneWindowManager 에서 처리는 마치 keyguard 에서 처리하는 것과 같다.
 
五、更新屏幕最亮化(Gēngxīn píngmù zuì liàng huà), 갱신 스크린 밝기

  我们再来看updateScreenBrightnessBoostLocked函数,也会调用mNotifier.onScreenBrightnessBoostChanged函数
   private void updateScreenBrightnessBoostLocked(int dirty) {
    if ((dirty & DIRTY_SCREEN_BRIGHTNESS_BOOST) != 0) {
     if (mScreenBrightnessBoostInProgress) {
      final long now = SystemClock.uptimeMillis();
      mHandler.removeMessages(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
      if (mLastScreenBrightnessBoostTime > mLastSleepTime) {
       final long boostTimeout = mLastScreenBrightnessBoostTime +
         SCREEN_BRIGHTNESS_BOOST_TIMEOUT;
       if (boostTimeout > now) {
        Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
        msg.setAsynchronous(true);
        mHandler.sendMessageAtTime(msg, boostTimeout);
        return;
       }
      }
      mScreenBrightnessBoostInProgress = false;
      mNotifier.onScreenBrightnessBoostChanged();
      userActivityNoUpdateLocked(now,
        PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
     }
    }
   }
  
  onScreenBrightnessBoostChanged函数(Hánshù),发送了消息(Fāsòngle xiāoxī) 메시지 보낸다.
   public void onScreenBrightnessBoostChanged() {

    mSuspendBlocker.acquire();// 持锁(Chí suǒ)了
    Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED);
    msg.setAsynchronous(true);
    mHandler.sendMessage(msg);
   }
 
  最后在sendBrightnessBoostChangedBroadcast处理了消息, 发送广播. 함수에서 메시지 처리가 되어지고, broadcast을 보낸다.
   private void sendBrightnessBoostChangedBroadcast() {
    if (DEBUG) {
     Slog.d(TAG, "Sending brightness boost changed broadcast.");
    }

    mContext.sendOrderedBroadcastAsUser(mScreenBrightnessBoostIntent, UserHandle.ALL, null,
      mScreeBrightnessBoostChangedDone, mHandler, 0, null, null);
   }


六、setWakefulnessLocked
  在PowerManagerService的每个setWakefulnessLocked,都会调用mNotifier.onWakefulnessChangeStarted函数
   private void setWakefulnessLocked(int wakefulness, int reason) {
    if (mWakefulness != wakefulness) {
     mWakefulness = wakefulness;
     mWakefulnessChanging = true;
     mDirty |= DIRTY_WAKEFULNESS;
     mNotifier.onWakefulnessChangeStarted(wakefulness, reason);
    }
   }

  Notifier的onWakefulnessChangeStarted函数:
   public void onWakefulnessChangeStarted(final int wakefulness, int reason) {
    final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);
    mHandler.post(new Runnable() {
     @Override
     public void run() {
      mActivityManagerInternal.onWakefulnessChanged(wakefulness); // 调用AMS的onWakefulnessChanged函数
     }
    });

    // Handle any early interactive state changes.
    // Finish pending incomplete ones from a previous cycle.
    if (mInteractive != interactive) { // 屏幕状态改变(Píngmù zhuàngtài gǎibiàn) 스크린 상태 변경
     // Finish up late behaviors if needed.
     if (mInteractiveChanging) {
      handleLateInteractiveChange();
     }

     // Start input as soon as we start waking up or going to sleep.
     mInputManagerInternal.setInteractive(interactive);
     mInputMethodManagerInternal.setInteractive(interactive);

     // Notify battery stats.
     try {
      mBatteryStats.noteInteractive(interactive);
     } catch (RemoteException ex) { }

     // Handle early behaviors.
     mInteractive = interactive;
     mInteractiveChangeReason = reason;
     mInteractiveChanging = true;
     handleEarlyInteractiveChange();
    }
   }
  
  我们先来看handleEarlyInteractiveChange函数
   private void handleEarlyInteractiveChange() {
    synchronized (mLock) {
     if (mInteractive) {
      // Waking up...
      mHandler.post(new Runnable() {
       @Override
       public void run() {
        EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
        mPolicy.startedWakingUp();//调用PhoneWindowManager
       }
      });

      // Send interactive broadcast.
      mPendingInteractiveState = INTERACTIVE_STATE_AWAKE;
      mPendingWakeUpBroadcast = true;
      updatePendingBroadcastLocked();//发送亮屏广播(Fāsòng liàng píng guǎngbò), LCD On broadcast 를 보낸다.
     } else {
      // Going to sleep...
      // Tell the policy that we started going to sleep.
      final int why = translateOffReason(mInteractiveChangeReason);
      mHandler.post(new Runnable() {
       @Override
       public void run() {
        mPolicy.startedGoingToSleep(why);//调用PhoneWindowManager
       }
      });
     }
    }
   }

  updatePendingBroadcastLocked发送消息处理广播(Chǔlǐ guǎngbò),并且持锁(Bìngqiě chí suǒ)Broadcast  - 그리고 Broadcast Locked 함
      private void updatePendingBroadcastLocked() {
    if (!mBroadcastInProgress
      && mPendingInteractiveState != INTERACTIVE_STATE_UNKNOWN
      && (mPendingWakeUpBroadcast || mPendingGoToSleepBroadcast
        || mPendingInteractiveState != mBroadcastedInteractiveState)) {
     mBroadcastInProgress = true;
     mSuspendBlocker.acquire(); //持锁(Locked)
     Message msg = mHandler.obtainMessage(MSG_BROADCAST);
     msg.setAsynchronous(true);
     mHandler.sendMessage(msg);
    }
   }


七、finishWakefulnessChangeIfNeededLocked
  在PowerManagerService的updatePowerState中会调用finishWakefulnessChangeIfNeededLocked函数,这个函数最后调用了mNotifier.onWakefulnessChangeFinished
   private void finishWakefulnessChangeIfNeededLocked() {
    if (mWakefulnessChanging && mDisplayReady) {
     if (mWakefulness == WAKEFULNESS_DOZING
       && (mWakeLockSummary & WAKE_LOCK_DOZE) == 0) {
      return; // wait until dream has enabled dozing
     }
     mWakefulnessChanging = false;
     mNotifier.onWakefulnessChangeFinished();
    }
   }

  onWakefulnessChangeFinished函数:
   public void onWakefulnessChangeFinished() {
    if (mInteractiveChanging) {
     mInteractiveChanging = false;
     handleLateInteractiveChange();
    }
   }

  这个函数调用了handleLateInteractiveChange函数
   private void handleLateInteractiveChange() {
    synchronized (mLock) {
     if (mInteractive) {
      // Finished waking up...
      mHandler.post(new Runnable() {
       @Override
       public void run() {
        mPolicy.finishedWakingUp();//PhoneWindowManager的finish wakeingUp
       }
      });
     } else {
      // Finished going to sleep...
      // This is a good time to make transitions that we don't want the user to see,
      // such as bringing the key guard to focus.  There's no guarantee for this
      // however because the user could turn the device on again at any time.
      // Some things may need to be protected by other mechanisms that defer screen on.

      // Cancel pending user activity.
      if (mUserActivityPending) {
       mUserActivityPending = false;
       mHandler.removeMessages(MSG_USER_ACTIVITY);
      }

      // Tell the policy we finished going to sleep.
      final int why = translateOffReason(mInteractiveChangeReason);
      mHandler.post(new Runnable() {
       @Override
       public void run() {
        EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0);
        mPolicy.finishedGoingToSleep(why);// phoneWindowManager的finsh goToSleep
       }
      });

      // Send non-interactive broadcast.
      mPendingInteractiveState = INTERACTIVE_STATE_ASLEEP;
      mPendingGoToSleepBroadcast = true;
      updatePendingBroadcastLocked();//发送广播
     }
    }
   }

  这第六和第七需要(xūyào)结合(jiéhé)起来看, onWakefulnessChangeStarted 是刚设置(shèzhì)状态, onWakefulnessChangeFinished 是设置状态结束了。
  제6와 7은 결합이 필요하니 보자, onWakefulnessChangeStarted은 바로 상태(state)를 설정(set)하고, onWakefulnessChangeFinished은 상태설정을 마친다.

  onWakefulnessChangeStarted函数中先调用handleEarlyInteractiveChange,然后onWakefulnessChangeFinished调用handleLateInteractiveChange,
  并且(bìngqiě, 게다가/그리고)用 mInteractiveChanging 变量(biànliàng, 변수)来控制(kòngzhì, 통제, 제어하다)。
  그리고 mInteractiveChanging변수를 제어하는 것이 필요하다.

  而 handleEarlyInteractiveChange 处理亮屏,先发广播调用 mPolicy.startedWakingUp,然后在handleLateInteractiveChange函数中mPolicy.finishedWakingUp而处理灭屏事件(shìjiàn),
  또한 handleEarlyInteractiveChange는 LCD On을 처리하고, 먼저 broadcast는 mPolicy.startedWakingUp 을 호출하고, 나중에 handleLateInteractiveChange 함수에서 mPolicy.finishedWakingUp 그리고 LCD Off 이벤트 처리를 함.

  现在handleEarlyInteractiveChange函数中 mPolicy.startedGoingToSleep, 然后在handleLateInteractiveChange函数中mPolicy.finishedGoingToSleep 然后发送灭屏广播。


八、总结(zǒngjié, 결론)
  我们主要(zhǔyào, 주요한, 주로)在这篇博客分析(piān bókè fēnxī)了,PowerManagerService的各个(gègè)状态变化后用Notifier类(lèi)做一些通知,
  比如(bǐrú)发送广播,通知 PhoneWindowManager,AMS的一些接口等。
  우리는 이 블로그/사이트/페이지에서 주로 분석을 했다, PowerManagerService의 각개의 상태 변화 후 Notifier class을 사용하여 some 알림(notice)을 한다.
  이와 같은 broadcast를 보내고, 통지(알림) PhoneWindowManager, AMS의 some 인터페이스 등.

List of Articles
번호 제목 글쓴이 날짜 조회 수
공지 개발 오디오 분석을 위한 소스 빌드 사전작업 secret eastsky 2010-12-16 3
공지 개발 Android Tips secret eastsky 2010-11-15 5
27 개발 Android6.0 - PowerManagerService状态分析 eastsky 2017-07-21 752
» 개발 Android6.0 - PowerManagerService Notifier 分析 eastsky 2017-07-21 705
25 개발 Android 개발 전반에 대한 연재 eastsky 2017-06-13 1159
24 개발 kBuild eastsky 2017-06-13 1137
23 개발 Kbuild system eastsky 2017-06-13 1360
22 개발 [Linux] make menuconfig 사용방법 [1] eastsky 2017-06-12 1629
21 개발 ADB 명령어 및 Log Filter eastsky 2017-06-12 1812
20 개발 GNU Make eastsky 2017-06-09 1397
19 개발 Android Build System [1] eastsky 2017-06-09 1662
18 개발 Linux and Android - Suspend / Resume eastsky 2012-12-24 30412
17 개발 안드로이드 터치 보정값을 얻자. file [1] 이종일 2011-02-23 42955
16 개발 Android에 BusyBox 첨가 하기. [3] 이종일 2011-02-22 48676
15 개발 Android 동호문서 따라하기 file 이종일 2011-02-18 29595
14 개발 Linux RamDisk 참고 자료 file 이종일 2011-02-17 33247
13 일반 Android 2.3 Platform Highlights eastsky 2010-12-08 20047
12 개발 안드로이드 초기화 과정 eastsky 2010-12-02 43045
11 일반 하이씨엘 앱 에디터 eastsky 2010-12-01 23703
10 개발 Android 2.2 - Market Client on ADV file eastsky 2010-11-30 26052
9 개발 Android 2.2 - SDK & AVD Manager file eastsky 2010-11-30 27316