日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android7.0 Doze模式分析(一)Doze介绍 amp; DeviceIdleController

發布時間:2024/4/17 Android 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android7.0 Doze模式分析(一)Doze介绍 amp; DeviceIdleController 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


參考:http://blog.csdn.net/gaugamela/article/details/52981984

在Android M中,Google就引入了Doze模式。它定義了一種全新的、低能耗的狀態。


?在該狀態,后臺僅僅有部分任務被同意執行。其他任務都被強制停止。

在之前的博客中分析過Doze模式。就是device idle狀態。可能有的地方分析的不是非常具體,如今在android7.0上又一次分析下。

一、基本原理

Doze模式能夠簡單概括為:
?若推斷用戶在連續的一段時間內沒有使用手機,就延緩終端中APP后臺的CPU和網絡活動,以達到降低電量消耗的目的。


上面這張圖比較經典,基本上說明了Doze模式的含義。
?圖中的橫軸表示時間。紅色部分表示終端處于喚醒的執行狀態,綠色部分就是Doze模式定義的休眠狀態。

從圖中的描寫敘述,我們能夠看到:假設一個用戶停止充電(on battery: 利用電池供電),關閉屏幕(screen off)。手機處于精巧狀態(stationary: 位置沒有發生相對移動)。保持以上條件一段時間之后,終端就會進入Doze模式。一旦進入Doze模式。系統就降低(延緩)應用對網絡的訪問、以及對CPU的占用,來節省電池電量。

如圖所看到的,Doze模式還定義了maintenance window。
?在maintenance window中。系統同意應用完畢它們被延緩的動作。即能夠使用CPU資源及訪問網絡。


?從圖中我們能夠看出。當進入Doze模式的條件一直滿足時,Doze模式會定期的進入到maintenance window,但進入的間隔越來越長。
?通過這樣的方式,Doze模式能夠使終端處于較長時間的休眠狀態。

須要注意的是:一旦Doze模式的條件不再滿足。即用戶充電、或打開屏幕、或終端的位置發生了移動,終端就恢復到正常模式。
?因此,當用戶頻繁使用手機時。Doze模式差點兒是沒有什么實際用處的。

詳細來講,當終端處于Doze模式時。進行了下面操作:
1、暫停網絡訪問。
2、系統忽略全部的WakeLock。
3、標準的AlarmManager alarms被延緩到下一個maintenance window。


?但使用AlarmManager的 setAndAllowWhileIdle、setExactAndAllowWhileIdle和setAlarmClock時,alarms定義事件仍會啟動。


?在這些alarms啟動前,系統會短暫地退出Doze模式。
4、系統不再進行WiFi掃描。
5、系統不同意sync adapters執行。
6、系統不同意JobScheduler執行。

另外我在還有一篇博客中:http://blog.csdn.net/kc58236582/article/details/50554174也具體介紹了Doze模式。能夠參考下,上面有一些命令使用等。


二、DeviceIdleController

Android中的Doze模式主要由DeviceIdleController來控制。

public class DeviceIdleController extends SystemServiceimplements AnyMotionDetector.DeviceIdleCallback

能夠看出DeviceIdleController繼承自SystemService,是一個系統級的服務。
同一時候,繼承了AnyMotionDetector定義的接口,便于檢測到終端位置變化后進行回調。

2.1 DeviceIdleController的初始化

接下來我們看看它的初始化過程。


private void startOtherServices() {.........mSystemServiceManager.startService(DeviceIdleController.class);......... }

如上代碼所看到的,SystemServer在startOtherServices中啟動了DeviceIdleController,將先后調用DeviceIdleController的構造函數和onStart函數。

構造函數

public DeviceIdleController(Context context) {super(context);//deviceidle.xml用于定義idle模式也能正常工作的非系統應用mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));mHandler = new MyHandler(BackgroundThread.getHandler().getLooper()); }

DeviceIdleController的構造函數比較簡單,就是在創建data/system/deviceidle.xml相應的file文件,同一時候創建一個相應于后臺線程的handler。這里的deviceidle.xml能夠在設置中的電池選項那里。

有電池優化,能夠將一些應用放到白名單中,調用DeviceIdleController的addPowerSaveWhitelistApp方法。最后會寫入deviceidle.xml文件,然后在下次開機的時候DeviceIdleController會又一次讀取deviceidle.xml文件然后放入白名單mPowerSaveWhitelistUserApps中。

onStart函數

public void onStart() {final PackageManager pm = getContext().getPackageManager();synchronized (this) {//讀取配置文件,推斷Doze模式是否同意被開啟mLightEnabled = mDeepEnabled = getContext().getResources().getBoolean(com.android.internal.R.bool.config_enableAutoPowerModes);//分析PKMS時提到過,PKMS掃描系統文件夾的xml,將形成SystemConfigSystemConfig sysConfig = SystemConfig.getInstance();//獲取除了device Idle模式外,都能夠執行的系統應用白名單ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle();for (int i=0; i<allowPowerExceptIdle.size(); i++) {String pkg = allowPowerExceptIdle.valueAt(i);try {ApplicationInfo ai = pm.getApplicationInfo(pkg,PackageManager.MATCH_SYSTEM_ONLY);int appid = UserHandle.getAppId(ai.uid);mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);} catch (PackageManager.NameNotFoundException e) {}}//獲取device Idle模式下,也能夠執行的系統應用白名單ArraySet<String> allowPower = sysConfig.getAllowInPowerSave();for (int i=0; i<allowPower.size(); i++) {String pkg = allowPower.valueAt(i);try {ApplicationInfo ai = pm.getApplicationInfo(pkg,PackageManager.MATCH_SYSTEM_ONLY);int appid = UserHandle.getAppId(ai.uid);// These apps are on both the whitelist-except-idle as well// as the full whitelist, so they apply in all cases.mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);mPowerSaveWhitelistApps.put(ai.packageName, appid);mPowerSaveWhitelistSystemAppIds.put(appid, true);} catch (PackageManager.NameNotFoundException e) {}}//Constants為deviceIdleController中的內部類,繼承ContentObserver//監控數據庫變化,同一時候得到Doze模式定義的一些時間間隔mConstants = new Constants(mHandler, getContext().getContentResolver());//解析deviceidle.xml,并將當中定義的package相應的app。增加到mPowerSaveWhitelistUserApps中readConfigFileLocked();//將白名單的內容給AlarmManagerService和PowerMangerService//比如:DeviceIdleController推斷開啟Doze模式時,會通知PMS//此時除去白名單相應的應用外,PMS會將其他全部的WakeLock設置為Disable狀態updateWhitelistAppIdsLocked();//下面的初始化,都是如果眼下處在進入Doze模式相反的條件上mNetworkConnected = true;mScreenOn = true;// Start out assuming we are charging. If we aren't, we will at least get// a battery update the next time the level drops.mCharging = true;//Doze模式定義終端初始時為ACTIVE狀態mState = STATE_ACTIVE;//屏幕狀態初始時為ACTIVE狀態mLightState = LIGHT_STATE_ACTIVE;mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;}//公布服務//BinderService和LocalService均為DeviceIdleController的內部類mBinderService = new BinderService();publishBinderService(Context.DEVICE_IDLE_CONTROLLER, mBinderService);publishLocalService(LocalService.class, new LocalService()); }

除去公布服務外。DeviceIdleController在onStart函數中。主要是讀取配置文件更新自己的變量,思路比較清晰。

在這里我們僅跟進一下updateWhitelistAppIdsLocked函數:

private void updateWhitelistAppIdsLocked() {//構造出除去idle模式外。可執行的app id數組 (可覺得是系統和普通應用的集合)//mPowerSaveWhitelistAppsExceptIdle從系統文件夾下的xml得到//mPowerSaveWhitelistUserApps從deviceidle.xml得到。或調用接口增加;//mPowerSaveWhitelistExceptIdleAppIds并未使用mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(mPowerSaveWhitelistAppsExceptIdle,mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds);//構造不受Doze限制的app id數組 (可覺得是系統和普通應用的集合)//mPowerSaveWhitelistApps從系統文件夾下的xml得到//mPowerSaveWhitelistAllAppIds并未使用mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps,mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);//構造不受Doze限制的app id數組(僅普通應用的集合)、//mPowerSaveWhitelistUserAppIds并未使用mPowerSaveWhitelistUserAppIdArray = buildAppIdArray(null,mPowerSaveWhitelistUserApps, mPowerSaveWhitelistUserAppIds);if (mLocalPowerManager != null) {...........//PMS拿到的是:系統和普通應用組成的不受Doze限制的app id數組 mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);}if (mLocalAlarmManager != null) {..........//AlarmManagerService拿到的是:普通應用組成的不受Doze限制的app id數組 mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray);} }

updateWhitelistAppIdsLocked主要是將白名單交給PMS和AlarmManagerService。
注意Android區分了系統應用白名單、普通應用白名單等,因此上面進行了一些合并操作。這里我們有沒有發現。systemConfig的app不會增加alarm的白名單,而在Settings中電池那邊設置的白名單,會增加Power wakelock的白名單。

onBootPhase函數

與PowerManagerService一樣,DeviceIdleController在初始化的最后一個階段須要調用onBootPhase函數:

public void onBootPhase(int phase) {//在系統PHASE_SYSTEM_SERVICES_READY階段,進一步完畢一些初始化if (phase == PHASE_SYSTEM_SERVICES_READY) {synchronized (this) {//初始化一些變量mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);..............mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);//依據配置文件,利用SensorManager獲取相應的傳感器,保存到mMotionSensor中..............//假設配置文件表明:終端須要預獲取位置信息//則構造LocationRequestif (getContext().getResources().getBoolean(com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) {mLocationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);mLocationRequest = new LocationRequest().setQuality(LocationRequest.ACCURACY_FINE).setInterval(0).setFastestInterval(0).setNumUpdates(1);}//依據配置文件。得到角度變化的門限float angleThreshold = getContext().getResources().getInteger(com.android.internal.R.integer.config_autoPowerModeThresholdAngle) / 100f;//創建一個AnyMotionDetector,同一時候將DeviceIdleController注冊到當中//當AnyMotionDetector檢測到手機變化角度超過門限時。就會回調DeviceIdleController的接口mAnyMotionDetector = new AnyMotionDetector((PowerManager) getContext().getSystemService(Context.POWER_SERVICE),mHandler, mSensorManager, this, angleThreshold);//創建兩個經常使用的Intent。用于通知Doze模式的變化mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY| Intent.FLAG_RECEIVER_FOREGROUND);mLightIdleIntent = new Intent(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);mLightIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY| Intent.FLAG_RECEIVER_FOREGROUND);//監聽ACTION_BATTERY_CHANGED廣播(電池信息發生改變)IntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_BATTERY_CHANGED);getContext().registerReceiver(mReceiver, filter);//監聽ACTION_PACKAGE_REMOVED廣播(包被移除)filter = new IntentFilter();filter.addAction(Intent.ACTION_PACKAGE_REMOVED);filter.addDataScheme("package");getContext().registerReceiver(mReceiver, filter);//監聽CONNECTIVITY_ACTION廣播(連接狀態發生改變)filter = new IntentFilter();filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);getContext().registerReceiver(mReceiver, filter);//又一次將白名單信息交給PowerManagerService和AlarmManagerService//這個工作在onStart函數中,已經調用updateWhitelistAppIdsLocked進行過了//到onBootPhase時。又一次進行一次,可能:一是為了保險。二是,其他進程可能調用接口,更改了相應數據,于是進行更新mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray);//監聽屏幕顯示相關的變化mDisplayManager.registerDisplayListener(mDisplayListener, null);//更新屏幕顯示相關的信息updateDisplayLocked();}//更新連接狀態相關的信息updateConnectivityState(null);} }

從代碼能夠看出。onBootPhase方法:
?主要創建一些本地變量。然后依據配置文件初始化一些傳感器,同一時候注冊了一些廣播接收器和回到接口。
?最后更新屏幕顯示和連接狀態相關的信息。


2.2 DeviceIdleController的狀態變化

充電狀態的處理

對于充電狀態,在onBootPhase函數中已經提到。DeviceIdleController監聽了ACTION_BATTERY_CHANGED廣播:

............ IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_CHANGED); getContext().registerReceiver(mReceiver, filter); ...........

我們看看receiver中相應的處理:

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {@Override public void onReceive(Context context, Intent intent) {switch (intent.getAction()) {.........case Intent.ACTION_BATTERY_CHANGED: {synchronized (DeviceIdleController.this) {//從廣播中得到是否在充電的消息int plugged = intent.getIntExtra("plugged", 0);updateChargingLocked(plugged != 0);}} break;}} }。依據上面的代碼,能夠看出當收到電池信息改變的廣播后,DeviceIdleController將得到電源是否在充電的消息,然后調用updateChargingLocked函數進行處理。
void updateChargingLocked(boolean charging) {.........if (!charging && mCharging) {//從充電狀態變為不充電狀態mCharging = false;//mForceIdle值一般為false,是通過dumpsys命令將mForceIdle改成true的if (!mForceIdle) {//推斷是否進入Doze模式becomeInactiveIfAppropriateLocked();}} else if (charging) {//進入充電狀態mCharging = charging;if (!mForceIdle) {//手機退出Doze模式becomeActiveLocked("charging", Process.myUid());}} }

becomeInactiveIfAppropriateLocked函數是開始進入Doze模式,而becomeActiveLocked是退出Doze模式。

顯示狀態處理

DeviceIdleController中注冊了顯示變化的回調

mDisplayManager.registerDisplayListener(mDisplayListener, null);回調會調用updateDisplayLocked函數
private final DisplayManager.DisplayListener mDisplayListener= new DisplayManager.DisplayListener() {@Override public void onDisplayAdded(int displayId) {}@Override public void onDisplayRemoved(int displayId) {}@Override public void onDisplayChanged(int displayId) {if (displayId == Display.DEFAULT_DISPLAY) {synchronized (DeviceIdleController.this) {updateDisplayLocked();}}}};

updateDisplayLocked函數和更新充電狀態的函數updateChargingLocked類似

void updateDisplayLocked() {mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);// We consider any situation where the display is showing something to be it on,// because if there is anything shown we are going to be updating it at some// frequency so can't be allowed to go into deep sleeps.boolean screenOn = mCurDisplay.getState() == Display.STATE_ON;if (DEBUG) Slog.d(TAG, "updateDisplayLocked: screenOn=" + screenOn);if (!screenOn && mScreenOn) {mScreenOn = false;if (!mForceIdle) {//開始進入Doze模式becomeInactiveIfAppropriateLocked();}} else if (screenOn) {//屏幕點亮。退出Doze模式mScreenOn = true;if (!mForceIdle) {becomeActiveLocked("screen", Process.myUid());}}}

becomeActiveLocked函數退出Doze模式

我們先來看看becomeActiveLocked函數

//activeReason記錄的終端變為active的原因 void becomeActiveLocked(String activeReason, int activeUid) {...........if (mState != STATE_ACTIVE || mLightState != STATE_ACTIVE) {............//1、通知PMS等Doze模式結束scheduleReportActiveLocked(activeReason, activeUid);//更新DeviceIdleController本地維護的狀態//在DeviceIdleController的onStart函數中。我們已經知道了//初始時,mState和mLightState均為Active狀態mState = STATE_ACTIVE;//state是指設備通過傳感器推斷進入idlemLightState = LIGHT_STATE_ACTIVE;//mLight是背光的狀態mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;mCurIdleBudget = 0;mMaintenanceStartTime = 0;//2、重置一些事件resetIdleManagementLocked();resetLightIdleManagementLocked();addEvent(EVENT_NORMAL);} }

scheduleReportActiveLocked函數就是發送MSG_REPORT_ACTIVE消息

void scheduleReportActiveLocked(String activeReason, int activeUid) {//發送MSG_REPORT_ACTIVE消息Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid, 0, activeReason);mHandler.sendMessage(msg); }

我們再看下消息的處理,主要調用了PowerManagerService的setDeviceIdleMode函數來退出Doze狀態,然后又一次更新wakelock的enable狀態。 以及通知NetworkPolicyManagerService不再限制應用上網,還有發送Doze模式改變的廣播。


......... case MSG_REPORT_ACTIVE: {.........//通知PMS Doze模式結束,//于是PMS將一些Doze模式下。disable的WakeLock又一次enable//然后調用updatePowerStateLocked函數更新終端的狀態final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false);final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);try {//通過NetworkPolicyManagerService更改Ip-Rule。不再限制終端應用上網mNetworkPolicyManager.setDeviceIdleMode(false);//BSS做好相應的記錄mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,activeReason, activeUid);} catch (RemoteException e) {}//發送廣播if (deepChanged) {getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);}if (lightChanged) {getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);} } ........

resetIdleManagementLocked函數就是取消alarm。檢測等。

void resetIdleManagementLocked() {//復位一些狀態變量mNextIdlePendingDelay = 0;mNextIdleDelay = 0;mNextLightIdleDelay = 0;//停止一些工作,主要是位置檢測相關的cancelAlarmLocked();cancelSensingTimeoutAlarmLocked();cancelLocatingLocked();stopMonitoringMotionLocked();mAnyMotionDetector.stop(); }


becomeInactiveIfAppropriateLocked函數開始進入Doze模式

becomeInactiveIfAppropriateLocked函數就是我們開始進入Doze模式的第一個步驟。以下我們就具體分析這個函數

void becomeInactiveIfAppropriateLocked() {.................//屏幕熄滅。未充電if ((!mScreenOn && !mCharging) || mForceIdle) {// Screen has turned off; we are now going to become inactive and start// waiting to see if we will ultimately go idle.if (mState == STATE_ACTIVE && mDeepEnabled) {mState = STATE_INACTIVE;...............//重置事件resetIdleManagementLocked();//開始檢測能否夠進入Doze模式的Idle狀態//若終端沒有watch feature, mInactiveTimeout時間為30minscheduleAlarmLocked(mInactiveTimeout, false);...............}if (mLightState == LIGHT_STATE_ACTIVE && mLightEnabled) {mLightState = LIGHT_STATE_INACTIVE;.............resetLightIdleManagementLocked();//重置事件scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT);}} }

要進入Doze流程,就是調用這個函數,首先要保證屏幕滅屏然后沒有充電。這里還有mDeepEnable和mLightEnable前面說過是在配置中定義的,一般默認是關閉(也就是不開Doze模式)。這里mLightEnabled是相應禁止wakelock持鎖的,禁止網絡。

而mDeepEnabled相應是檢測設備是否精巧,除了禁止wakelock、禁止網絡、還會機制alarm。


light idle模式

我們先看light idle模式,這個模式下、會禁止網絡、wakelock。可是不會禁止alarm。

我們先看scheduleLightAlarmLocked函數。這里設置了一個alarm。delay是5分鐘。

到時間后調用mLightAlarmListener回調。

void scheduleLightAlarmLocked(long delay) {if (DEBUG) Slog.d(TAG, "scheduleLightAlarmLocked(" + delay + ")");mNextLightAlarmTime = SystemClock.elapsedRealtime() + delay;mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,mNextLightAlarmTime, "DeviceIdleController.light", mLightAlarmListener, mHandler);}

mLightAlarmListener就是進入lightidle,調用stepLightIdleStateLocked函數

private final AlarmManager.OnAlarmListener mLightAlarmListener= new AlarmManager.OnAlarmListener() {@Overridepublic void onAlarm() {synchronized (DeviceIdleController.this) {stepLightIdleStateLocked("s:alarm");}}};

我們來看stepLightIdleStateLocked函數,這個函數會處理mLightState不同狀態。會依據不同狀態,然后設置alarm。到時間后繼續處理下個狀態。到LIGHT_STATE_IDLE_MAINTENANCE狀態處理時。會發送MSG_REPORT_IDLE_ON_LIGHT。這個消息的處理會禁止網絡、禁止wakelock。然后到LIGHT_STATE_WAITING_FOR_NETWORK,會先退出Doze狀態(這個時候網絡、wakelock恢復)。然后設置alarm。alarm時間到后,還是在LIGHT_STATE_IDLE_MAINTENANCE狀態。

和之前一樣(禁止網絡、wakelock)。

僅僅是設置的alarm間隔會越來越大。也就是僅僅要屏幕滅屏后。時間越長。設備會隔越來越長的時間才會退出Doze狀態。這也符合一個實際情況,可是會有一個上限值。


void stepLightIdleStateLocked(String reason) {if (mLightState == LIGHT_STATE_OVERRIDE) {// If we are already in deep device idle mode, then// there is nothing left to do for light mode.return;}EventLogTags.writeDeviceIdleLightStep();switch (mLightState) {case LIGHT_STATE_INACTIVE:mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;// Reset the upcoming idle delays.mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;mMaintenanceStartTime = 0;if (!isOpsInactiveLocked()) {// We have some active ops going on... give them a chance to finish// before going in to our first idle.mLightState = LIGHT_STATE_PRE_IDLE;EventLogTags.writeDeviceIdleLight(mLightState, reason);scheduleLightAlarmLocked(mConstants.LIGHT_PRE_IDLE_TIMEOUT);//設置alarm,時間到后到下個步驟break;}// Nothing active, fall through to immediately idle.case LIGHT_STATE_PRE_IDLE:case LIGHT_STATE_IDLE_MAINTENANCE:if (mMaintenanceStartTime != 0) {long duration = SystemClock.elapsedRealtime() - mMaintenanceStartTime;if (duration < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {// We didn't use up all of our minimum budget; add this to the reserve.mCurIdleBudget += (mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET-duration);} else {// We used more than our minimum budget; this comes out of the reserve.mCurIdleBudget -= (duration-mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET);}}mMaintenanceStartTime = 0;scheduleLightAlarmLocked(mNextLightIdleDelay);mNextLightIdleDelay = Math.min(mConstants.LIGHT_MAX_IDLE_TIMEOUT,(long)(mNextLightIdleDelay * mConstants.LIGHT_IDLE_FACTOR));if (mNextLightIdleDelay < mConstants.LIGHT_IDLE_TIMEOUT) {mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;}if (DEBUG) Slog.d(TAG, "Moved to LIGHT_STATE_IDLE.");mLightState = LIGHT_STATE_IDLE;EventLogTags.writeDeviceIdleLight(mLightState, reason);addEvent(EVENT_LIGHT_IDLE);mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT);//發送消息。這個消息處理就會關閉網絡,禁止wakelockbreak;case LIGHT_STATE_IDLE:case LIGHT_STATE_WAITING_FOR_NETWORK:if (mNetworkConnected || mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) {// We have been idling long enough, now it is time to do some work.mActiveIdleOpCount = 1;mActiveIdleWakeLock.acquire();mMaintenanceStartTime = SystemClock.elapsedRealtime();if (mCurIdleBudget < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;} else if (mCurIdleBudget > mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET) {mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;}scheduleLightAlarmLocked(mCurIdleBudget);if (DEBUG) Slog.d(TAG,"Moved from LIGHT_STATE_IDLE to LIGHT_STATE_IDLE_MAINTENANCE.");mLightState = LIGHT_STATE_IDLE_MAINTENANCE;EventLogTags.writeDeviceIdleLight(mLightState, reason);addEvent(EVENT_LIGHT_MAINTENANCE);mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);//醒一下(開啟網絡、恢復wakelock)} else {// We'd like to do maintenance, but currently don't have network// connectivity... let's try to wait until the network comes back.// We'll only wait for another full idle period, however, and then give up.scheduleLightAlarmLocked(mNextLightIdleDelay);if (DEBUG) Slog.d(TAG, "Moved to LIGHT_WAITING_FOR_NETWORK.");mLightState = LIGHT_STATE_WAITING_FOR_NETWORK;EventLogTags.writeDeviceIdleLight(mLightState, reason);}break;}}

可是這里僅僅是一個light idle。一旦進入deep idle,light idle設置的alarm會無效的(這個后面細說)。也就是說light idle一旦進入deep idle后無效了(由于idle step主要靠alarm驅動,而alarm無效后自然就驅動不了)。

deep idle模式

以下我們再來看deep idle模式,這個模式除了禁止網絡、wakelock還會禁止alarm。

我們再來看becomeInactiveIfAppropriateLocked函數中以下代碼。是關于deep idle的設置 這里的mInactiveTimeout是半小時

void becomeInactiveIfAppropriateLocked() {if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");if ((!mScreenOn && !mCharging) || mForceIdle) {// Screen has turned off; we are now going to become inactive and start// waiting to see if we will ultimately go idle.if (mState == STATE_ACTIVE && mDeepEnabled) {mState = STATE_INACTIVE;if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");resetIdleManagementLocked();scheduleAlarmLocked(mInactiveTimeout, false);EventLogTags.writeDeviceIdle(mState, "no activity");}

我們來看下scheduleAlarmLocked函數,注意假設這里參數idleUntil是true會調用AlarmManager的setIdleUntil函數,調用這個函數后普通應用設置alarm將失效。


void scheduleAlarmLocked(long delay, boolean idleUntil) {if (mMotionSensor == null) {//在onBootPhase時,獲取過位置檢測傳感器//假設終端沒有配置位置檢測傳感器,那么終端永遠不會進入到真正的Doze ilde狀態// If there is no motion sensor on this device, then we won't schedule// alarms, because we can't determine if the device is not moving.return;}mNextAlarmTime = SystemClock.elapsedRealtime() + delay;if (idleUntil) {//此時IdleUtil的值為falsemAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP,mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);} else {//30min后喚醒,調用mDeepAlarmListener的onAlarm函數mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);} }

須要注意的是,DeviceIdleController一直在監控屏幕狀態和充電狀態,一但不滿足Doze模式的條件。前面提到的becomeActiveLocked函數就會被調用。

mAlarmManager設置的定時喚醒事件將被取消掉,mDeepAlarmListener的onAlarm函數不會被調用。

因此,我們知道了終端必須保持Doze模式的入口條件長達30min,才會進入mDeepAlarmListener.onAlarm:

private final AlarmManager.OnAlarmListener mDeepAlarmListener= new AlarmManager.OnAlarmListener() {@Overridepublic void onAlarm() {synchronized (DeviceIdleController.this) {//進入到stepIdleStateLocked函數stepIdleStateLocked("s:alarm");}} };

以下我們就來看下stepIdleStateLocked函數:

void stepIdleStateLocked(String reason) {..........final long now = SystemClock.elapsedRealtime();//個人認為。以下這段代碼。是針對Idle狀態設計的//假設在Idle狀態收到Alarm,那么將先喚醒終端,然后又一次推斷是否須要進入Idle態//在介紹Doze模式原理時提到過,若應用調用AlarmManager的一些指定接口,仍然能夠在Idle狀態進行工作if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) {// Whoops, there is an upcoming alarm. We don't actually want to go idle.if (mState != STATE_ACTIVE) {becomeActiveLocked("alarm", Process.myUid());becomeInactiveIfAppropriateLocked();}return;}//以下是Doze模式的狀態轉變相關的代碼switch (mState) {case STATE_INACTIVE:// We have now been inactive long enough, it is time to start looking// for motion and sleep some more while doing so.//保持屏幕熄滅。同一時候未充電達到30min,進入此分支//注冊一個mMotionListener,檢測是否移動//假設檢測到移動,將又一次進入到ACTIVE狀態//對應代碼比較直觀,此處不再深入分析startMonitoringMotionLocked();//再次調用scheduleAlarmLocked函數,此次的時間仍為30min//也就說假設不發生退出Doze模式的事件。30min后將再次進入到stepIdleStateLocked函數//只是屆時的mState已經變為STATE_IDLE_PENDINGscheduleAlarmLocked(mConstants.IDLE_AFTER_INACTIVE_TIMEOUT, false);// Reset the upcoming idle delays.//mNextIdlePendingDelay為5minmNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;//mNextIdleDelay為60minmNextIdleDelay = mConstants.IDLE_TIMEOUT;//狀態變為STATE_IDLE_PENDING mState = STATE_IDLE_PENDING;............break;case STATE_IDLE_PENDING://保持息屏、未充電、精巧狀態,經過30min后。進入此分支mState = STATE_SENSING;//保持Doze模式條件,4min后再次進入stepIdleStateLockedscheduleSensingTimeoutAlarmLocked(mConstants.SENSING_TIMEOUT);//停止定位相關的工作cancelLocatingLocked();mNotMoving = false;mLocated = false;mLastGenericLocation = null;mLastGpsLocation = null;//開始檢測手機是否發生運動(這里應該是更仔細的側重于角度的變化)//若手機運動過。則又一次變為active狀態mAnyMotionDetector.checkForAnyMotion();break;case STATE_SENSING://上面的條件滿足后。進入此分支。開始獲取定位信息cancelSensingTimeoutAlarmLocked();mState = STATE_LOCATING;............//保持條件30s,再次調用stepIdleStateLockedscheduleAlarmLocked(mConstants.LOCATING_TIMEOUT, false);//網絡定位if (mLocationManager != null&& mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {mLocationManager.requestLocationUpdates(mLocationRequest,mGenericLocationListener, mHandler.getLooper());mLocating = true;} else {mHasNetworkLocation = false;}//GPS定位if (mLocationManager != null&& mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {mHasGps = true;mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5,mGpsLocationListener, mHandler.getLooper());mLocating = true;} else {mHasGps = false;}// If we have a location provider, we're all set, the listeners will move state// forward.if (mLocating) {//無法定位則直接進入下一個casebreak;}case STATE_LOCATING://停止定位和運動檢測,直接進入到STATE_IDLE_MAINTENANCEcancelAlarmLocked();cancelLocatingLocked();mAnyMotionDetector.stop();case STATE_IDLE_MAINTENANCE://進入到這個case后,終端開始進入Idle狀態,也就是真正的Doze模式//定義退出Idle的時間此時為60minscheduleAlarmLocked(mNextIdleDelay, true);............//退出周期逐步遞增,每次乘2mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR);...........//周期有最大值6hmNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);if (mNextIdleDelay < mConstants.IDLE_TIMEOUT) {mNextIdleDelay = mConstants.IDLE_TIMEOUT;}mState = STATE_IDLE;...........//通知PMS、NetworkPolicyManagerService等Doze模式開啟。即進入Idle狀態//此時PMS disable一些非白名單WakeLock。NetworkPolicyManagerService開始限制一些應用的網絡訪問//消息處理的詳細流程比較直觀,此處不再深入分析mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);break;case STATE_IDLE://進入到這個case時,本次的Idle狀態臨時結束,開啟maintenance window// We have been idling long enough, now it is time to do some work.mActiveIdleOpCount = 1;mActiveIdleWakeLock.acquire();//定義又一次進入Idle的時間為5min (也就是手機可處于Maintenance window的時間)scheduleAlarmLocked(mNextIdlePendingDelay, false);mMaintenanceStartTime = SystemClock.elapsedRealtime();//調整mNextIdlePendingDelay。乘2(最大為10min)mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT,(long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR));if (mNextIdlePendingDelay < mConstants.IDLE_PENDING_TIMEOUT) {mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;}mState = STATE_IDLE_MAINTENANCE;...........//通知PMS等臨時退出了Idle狀態。能夠進行一些工作//此時PMS enable一些非白名單WakeLock;NetworkPolicyManagerService開始同意應用的網絡訪問mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);break;} }

上面的流程在凝視里面已經非常明確了,而我們在進入Deep idle時。發送了一個MSG_REPORT_IDLE_ON消息。我們看以下這個消息的處理和之前的MSG_REPORT_IDLE_ON_LIGHT一樣的。關閉網絡。禁止wakelock。

case MSG_REPORT_IDLE_ON:case MSG_REPORT_IDLE_ON_LIGHT: {EventLogTags.writeDeviceIdleOnStart();final boolean deepChanged;final boolean lightChanged;if (msg.what == MSG_REPORT_IDLE_ON) {deepChanged = mLocalPowerManager.setDeviceIdleMode(true);lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);} else {deepChanged = mLocalPowerManager.setDeviceIdleMode(false);lightChanged = mLocalPowerManager.setLightDeviceIdleMode(true);}try {mNetworkPolicyManager.setDeviceIdleMode(true);mBatteryStats.noteDeviceIdleMode(msg.what == MSG_REPORT_IDLE_ON? BatteryStats.DEVICE_IDLE_MODE_DEEP: BatteryStats.DEVICE_IDLE_MODE_LIGHT, null, Process.myUid());} catch (RemoteException e) {}if (deepChanged) {getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);}if (lightChanged) {getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);}EventLogTags.writeDeviceIdleOnComplete();} break;

而禁止alarm是通過調用例如以下函數,注意參數是true。參數是true會調用mAlarmManager.setIdleUntil函數。這樣其它的alarm會被滯后(除非在白名單中)

scheduleAlarmLocked(mNextIdleDelay, true);

而每隔一段時間會進入Maintenance window的時間,此時是通過發送MSG_REPORT_IDLE_OFF消息,來恢復網絡和wakelock。

而這個時候之前設置的mAlarmManager.setIdleUntil的alarm也到期了,因此其它alarm也恢復了。

可是這個時間僅僅有5分鐘,又一次設置了alarm再次進入deep idle狀態。

Idle總結

當手機關閉屏幕或者拔掉電源的時候。手機開始推斷是否進入Doze模式。

Doze模式分兩種,第一種是light idle:

1.light idle

light idle在手機滅屏且沒有充電狀態下。5分鐘開始進入light idle流程。

然后第一次進入LIGHT_STATE_INACTIVE流程時,會再定義一個10分鐘的alarm。然后系統進入light idle狀態。這個狀態會使不是白名單的應用禁止訪問網絡,以及持wakelock鎖。

2.deep idle

deep idle除了light idle的狀態還會把非白名單中應用的alarm也禁止了。
?此時,系統中非白名單的應用將被禁止訪問網絡,它們申請的Wakelock也會被disable。


?從上面的代碼能夠看出,系統會周期性的退出Idle狀態。進入到MAINTENANCE狀態。集中處理相關的任務。


?一段時間后,會又一次再次回到IDLE狀態。

每次進入IDLE狀態,停留的時間都會是上次的2倍。最大時間限制為6h。

當手機運動。或者點亮屏幕,插上電源等。系統都會又一次返回到ACTIVIE狀態。

這里盜用別人的一樣圖,但不過deep idle的狀態:

(這里特別說明下,alarm和wakelock都是由DeviceIdleController主動調用相關接口設置的。而網絡是調用了DeviceIdleController的getAppIdWhitelist接口來獲取應用的白名單的,從而禁止非白名單訪問網絡。)


網絡我們不分析了,之前我們在Android6.0時分析過idle狀態下alarm和wakelock。7.0略微有點不一樣,以下兩篇博客又一次分析下吧。

總結

以上是生活随笔為你收集整理的Android7.0 Doze模式分析(一)Doze介绍 amp; DeviceIdleController的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

国产伦精品一区二区三区高清 | 国产视频手机在线 | 99在线精品观看 | 成人国产精品免费观看 | av在线播放免费 | av免费观看网站 | 欧美最猛性xxxxx(亚洲精品) | 国产视频首页 | 天天躁天天操 | 超碰在线人人97 | 中文字幕在线免费 | 国偷自产中文字幕亚洲手机在线 | 日韩美精品视频 | 米奇影视7777| 日本福利视频在线 | 久草热久草视频 | 亚洲精品五月天 | 少妇性bbb搡bbb爽爽爽欧美 | 国产免费观看av | 国产欧美久久久精品影院 | 天天干,夜夜操 | 最近久乱中文字幕 | 五月婷婷黄色网 | 成人黄色电影在线播放 | 日本精品二区 | 国产视频久久久 | 欧美激情第八页 | 午夜国产福利在线 | 最近日本字幕mv免费观看在线 | 日韩xxxbbb | 涩涩网站在线看 | www在线观看视频 | 在线亚洲成人 | 黄色小说在线观看视频 | 黄色成人毛片 | 国产精品三级视频 | 超碰在线人人97 | 草久草久| 久久午夜国产精品 | 午夜国产一区二区三区四区 | 美女网站在线看 | www.com久久久 | 国产日韩欧美在线观看视频 | 视频直播国产精品 | 国产精品精品国产婷婷这里av | 色综合久久中文综合久久牛 | 国产网站av | 国产欧美久久久精品影院 | 色91av | 久久视频免费在线 | ww视频在线观看 | 天天躁天天操 | 97视频人人澡人人爽 | 91精品中文字幕 | 日韩午夜视频在线观看 | 亚洲精品456在线播放第一页 | 一区二区 精品 | 中文字幕在线人 | 在线成人短视频 | 99riav1国产精品视频 | 久久色视频 | 中文字幕免费一区 | av线上免费观看 | 一级全黄毛片 | 97精品久久人人爽人人爽 | 国产最新网站 | 欧美三级高清 | 夜夜躁日日躁 | 国产亚洲一区 | 免费av网站在线 | 国产中文字幕在线免费观看 | 四虎成人精品在永久免费 | 成年人看片网站 | 玖玖国产精品视频 | 日韩毛片在线播放 | 国内小视频 | 人人澡人摸人人添学生av | 久久久精品久久日韩一区综合 | 蜜桃传媒一区二区 | 精品国产诱惑 | 日日夜夜天天久久 | 毛片网免费 | 在线精品视频免费播放 | 精品视频免费观看 | 久久女同性恋中文字幕 | 久久男女视频 | 成人免费视频网站 | 成人a级黄色片 | 午夜精品一区二区三区四区 | a黄色片在线观看 | 久草视频2| 亚洲在线看 | 99热手机在线 | 欧美日韩啪啪 | 在线观看你懂的网站 | www免费黄色 | wwwww.国产| 五月激情视频 | 96av麻豆蜜桃一区二区 | 丁香 婷婷 激情 | 四虎影视4hu4虎成人 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 四虎成人免费观看 | 91最新网址 | www.av小说| 久久男人中文字幕资源站 | 国产一级不卡视频 | 久久精品2 | 91看片网址 | av在线进入 | 激情影音 | 国产日韩欧美网站 | 免费在线黄网 | 久久国产高清 | www.99热精品 | 婷婷夜夜 | 午夜av一区二区三区 | 久久福利影视 | 国产一级片播放 | www.av中文字幕.com | 国产精品久久久久久999 | 亚洲国内精品在线 | 成人在线播放视频 | 成人啪啪18免费游戏链接 | 五月综合激情 | 免费观看www小视频的软件 | 国产精品视频免费观看 | 在线视频中文字幕一区 | 免费看的黄色小视频 | 久久久久女人精品毛片 | 天天色影院 | 丁香 久久 综合 | 在线电影a | 日韩免费一区二区在线观看 | 久久综合久久综合久久综合 | 欧美性大战 | 日本中文字幕在线 | 国产成人一二片 | 东方av在| 麻豆视频免费入口 | 亚洲国产片色 | 99九九热只有国产精品 | 黄色视屏免费在线观看 | 麻豆91精品视频 | 亚洲毛片在线观看. | 天天干天天草 | 999热视频| 狠狠狠色丁香综合久久天下网 | 五月天中文在线 | 国产区精品在线观看 | 黄色软件网站在线观看 | 久久视了 | 免费看的黄色网 | 这里有精品在线视频 | 日韩毛片在线免费观看 | 久久香蕉影视 | 色中文字幕在线观看 | 免费aa大片 | 天天艹天天 | 国产资源站 | 久久综合给合久久狠狠色 | 日韩免费观看一区二区三区 | 99精品视频免费在线观看 | 久久久一本精品99久久精品 | 国产福利资源 | 国产麻豆精品95视频 | 中文国产字幕 | 国产高清99| 日韩电影黄色 | 免费在线观看中文字幕 | 国产91精品一区二区绿帽 | 综合久久网站 | 看片黄网站 | 国内少妇自拍视频一区 | 九九久久国产 | 91精品成人久久 | 亚洲精品欧美成人 | 色综合咪咪久久网 | 狠狠干成人综合网 | 久久视频这里有精品 | 欧美极品xxx | 一区二区三区 亚洲 | 欧美一级大片在线观看 | 久久国产香蕉视频 | av在线网站大全 | 日韩电影中文字幕在线 | 黄色av电影免费观看 | 日本久久精品视频 | 亚洲一区二区三区91 | 一区二区免费不卡在线 | 81国产精品久久久久久久久久 | 亚洲理论视频 | 亚洲三级性片 | 天天色天天干天天 | 狠狠干网| 黄色美女免费网站 | 亚洲一级片免费观看 | av高清在线| 日韩在线免费不卡 | 亚洲国产精品视频 | 中文字幕 成人 | 久久久999 | 天天操天天操天天操 | 色欧美日韩 | 91精品办公室少妇高潮对白 | 国产 视频 高清 免费 | av一级黄| 蜜臀久久99精品久久久无需会员 | 69av视频在线观看 | 国产九九在线 | 超碰在线人 | 午夜免费电影院 | 丁香激情五月婷婷 | 久久精品美女视频 | 婷婷激情综合 | 久久这里精品视频 | av成人免费| 伊人干综合| 五月天亚洲综合小说网 | 免费观看视频的网站 | 日韩欧美国产视频 | 五月天开心| 最新av网址在线观看 | 美女在线免费观看视频 | 久久国产一区二区三区 | 亚洲精品久久激情国产片 | 99久久综合国产精品二区 | 免费看久久久 | 亚洲,播放 | 永久免费精品视频网站 | 成人黄色电影免费观看 | 国产精品成久久久久三级 | aaa日本高清在线播放免费观看 | 婷婷在线精品视频 | 久精品视频在线 | 久久噜噜少妇网站 | 欧美一级免费 | 国产成视频在线观看 | 天天弄天天干 | 亚洲天堂网站视频 | 成人毛片一区 | 四虎永久免费在线观看 | 狠狠综合久久 | 久久精品欧美日韩精品 | av色综合| 有码中文字幕 | 久久精品超碰 | 国产精品一区在线播放 | 亚洲人片在线观看 | 一级黄色网址 | 天天综合视频在线观看 | 97精品国产aⅴ| 天天操夜夜操夜夜操 | 亚洲高清在线视频 | 国产精品日韩欧美 | 成人一级在线 | 精品999| 国产精品尤物 | 精品一区二区在线免费观看 | 国产成人在线免费观看 | 在线观看视频色 | 亚洲精品久久久久久国 | 夜色.com| 国产精品精品国产 | 亚洲aⅴ在线观看 | 国产一区二区在线观看视频 | 色狠狠一区二区 | 日韩欧美国产激情在线播放 | 狠狠色丁香久久婷婷综 | 天天综合中文 | 最新日韩视频 | a√天堂资源 | 久久久久福利视频 | 亚洲爽爽网 | 国产在线色站 | 欧美淫aaa免费观看 日韩激情免费视频 | 最新日韩视频 | 97电影院网| 色婷婷狠| 午夜精品电影一区二区在线 | 日韩视频在线不卡 | 99热在线免费观看 | 草久中文字幕 | 国产精品精品久久久久久 | 国产 日韩 欧美 在线 | 国产一级二级视频 | 久久福利 | 久久五月天色综合 | 国产在线理论片 | 中文字幕一区2区3区 | 在线观看视频亚洲 | 色婷婷国产精品一区在线观看 | 国产区第一页 | 91片黄在线观 | 日韩视频中文字幕在线观看 | 蜜臀精品久久久久久蜜臀 | 国产成人精品电影久久久 | 久久婷婷色 | 欧美精品久久久久久久久久久 | 国产亚洲日本 | 欧美小视频在线 | 婷婷干五月 | 国产亚洲精品成人av久久影院 | 91精品在线观看视频 | 国产亚洲婷婷免费 | 亚洲一区二区三区毛片 | 六月色丁 | 久久与婷婷 | 日日夜夜草 | 在线а√天堂中文官网 | 国产中出在线观看 | 国产在线精品一区 | 久久久国产精品网站 | 精品久久免费看 | 黄色精品在线看 | 精品一二区 | 国产人成在线观看 | av在线播放快速免费阴 | 超碰人人在 | 美女黄频在线观看 | 亚洲黄色app | 亚洲男男gaygay无套同网址 | 91麻豆精品一区二区三区 | 在线观看不卡的av | 蜜臀久久99静品久久久久久 | 免费91麻豆精品国产自产在线观看 | 麻豆高清免费国产一区 | 国内小视频在线观看 | 91av网址 | www.夜夜爽 | 91手机视频在线 | 久久婷亚洲五月一区天天躁 | 亚洲色图22p| 成人久久久电影 | 91网免费观看 | 日韩一区正在播放 | 日本 在线 视频 中文 有码 | 在线观看精品一区 | 91视频麻豆视频 | 日韩免费成人 | 久久亚洲私人国产精品va | 91精品久久香蕉国产线看观看 | 国产特级毛片aaaaaa | 国产第一页在线播放 | 在线播放亚洲 | 中文字幕中文字幕在线中文字幕三区 | 久久久久亚洲最大xxxx | 精品国产免费人成在线观看 | 黄网站app在线观看免费视频 | 天天曰天天爽 | 懂色av一区二区三区蜜臀 | 好看的国产精品视频 | 久久久国产一区二区 | 97超碰人人模人人人爽人人爱 | 欧美一二区视频 | 亚洲片在线 | 99久久精品免费 | 99久久99 | 免费看黄色小说的网站 | 天天射天天干天天爽 | 在线免费国产视频 | 热久久最新地址 | 亚洲精品黄 | 中文字幕在线一区观看 | 在线播放 日韩专区 | 免费日韩一区二区三区 | 亚洲黄色激情小说 | 久久国产视屏 | 99精品久久精品一区二区 | 精品在线看 | 国产成a人亚洲精v品在线观看 | 可以免费观看的av片 | 国产成人av在线 | 视频一区二区三区视频 | 天天天干天天天操 | 久久激五月天综合精品 | 婷婷精品国产欧美精品亚洲人人爽 | 看黄色91 | 日韩久久一区二区 | 中文字幕av电影下载 | 国产91精品高清一区二区三区 | 在线免费观看av网站 | 91网免费看| 日本不卡一区二区三区在线观看 | 免费观看完整版无人区 | 日韩美在线 | 亚洲免费不卡 | 国产精品精品国产婷婷这里av | 久久久av免费 | 免费高清在线观看电视网站 | 成人影片在线免费观看 | 黄色小说在线观看视频 | 久久久久久美女 | 人人爱爱人人 | 五月天国产精品 | 久久色视频 | 国产日韩欧美在线免费观看 | 日日爱影视 | 国产一区二区久久精品 | 日日爽夜夜操 | 伊人久久电影网 | 中日韩三级视频 | 亚洲免费精品视频 | 黄色特级一级片 | 免费精品国产va自在自线 | 国产一卡久久电影永久 | 九九色网| 中国一级片在线观看 | 亚洲在线日韩 | 久久久久久欧美二区电影网 | 国产一级大片在线观看 | 亚洲成av人片在线观看 | 日韩在线欧美在线 | 日韩一区在线播放 | 四虎影视成人永久免费观看亚洲欧美 | 一区二区三区动漫 | 日韩欧美综合视频 | 伊人伊成久久人综合网站 | 亚洲波多野结衣 | av中文字幕免费在线观看 | 色五月激情五月 | 久久国产精品一区二区三区四区 | 欧美色伊人 | 久久免费看毛片 | 成人av日韩 | 日韩亚洲欧美中文字幕 | 丁香五香天综合情 | 色综合天天狠狠 | 色夜影院| 午夜天使 | 999国内精品永久免费视频 | 热久久最新地址 | 中文字幕日韩免费视频 | 麻花传媒mv免费观看 | 九色福利视频 | 天天激情| 99久久精品久久亚洲精品 | 亚洲一二视频 | 中文字幕日韩精品有码视频 | 人人干人人上 | 日日天天 | 国产91学生粉嫩喷水 | 胖bbbb搡bbbb擦bbbb| 亚洲黄色成人 | 亚洲午夜精 | 99九九99九九九视频精品 | 天天超碰 | 玖玖玖国产精品 | 人人干网| 五月视频 | 国产999精品久久久久久麻豆 | 亚洲精品麻豆 | 国产精品18videosex性欧美 | 18性欧美xxxⅹ性满足 | 9999毛片| 91专区在线观看 | 婷婷中文字幕综合 | 午夜性福利 | 毛片在线网 | 99久久这里有精品 | 日韩高清一二三区 | 最近高清中文字幕在线国语5 | 免费进去里的视频 | 亚洲精品黄网站 | 岛国一区在线 | 久久一区二区三区国产精品 | 不卡的av中文字幕 | 欧美成人精品欧美一级乱黄 | 婷婷丁香狠狠爱 | 天天曰夜夜爽 | 国产精品99久久久久 | 亚洲一区在线看 | 91精品国产自产老师啪 | 久久午夜免费视频 | 中文字幕中文 | 久久国产亚洲精品 | 免费又黄又爽视频 | 免费黄色av片 | 亚色视频在线观看 | 日韩av中文字幕在线 | 天天干.com | 国产亚洲一级高清 | av在线a | 久久久999免费视频 日韩网站在线 | 久碰视频在线观看 | 国产黄色片一级三级 | 超碰公开在线观看 | 五月婷婷开心中文字幕 | 日韩免费观看视频 | 成人在线观看日韩 | 91成人在线网站 | 97理论电影 | 成人资源网 | 亚洲电影第一页av | 久久99精品久久久久久秒播蜜臀 | 97成人在线| 久久成人麻豆午夜电影 | 97在线观看免费高清完整版在线观看 | 尤物一区二区三区 | 国产精品网站一区二区三区 | 亚洲免费不卡 | 色插综合| 一区二区视频在线免费观看 | 久久综合九色综合97_ 久久久 | 成片视频在线观看 | 国产香蕉久久 | 狠狠的操你 | 中文字幕不卡在线88 | 在线观看香蕉视频 | 国产精品电影在线 | 久久久久激情电影 | 成人久久久久久久久久 | 黄色在线网站噜噜噜 | 超碰97久久 | 一本一道久久a久久精品蜜桃 | 99视频播放 | 免费观看性生活大片3 | 亚洲无吗av| 国产高清福利在线 | 久久国产系列 | 成年免费在线视频 | 久久久久国产一区二区三区 | 9在线观看免费高清完整版在线观看明 | 国产视频2021| 福利一区视频 | 五月天久久综合网 | 日日碰狠狠添天天爽超碰97久久 | 亚洲黄色片一级 | 一本一本久久a久久精品牛牛影视 | 最新国产中文字幕 | 国产精品 中文在线 | 久久精品免费播放 | 亚洲国产成人精品在线观看 | 三日本三级少妇三级99 | 欧美日韩精品在线一区二区 | 六月婷色| 99爱爱| 00av视频 | 中文字幕成人在线观看 | 日躁夜躁狠狠躁2001 | 国产成人久久精品77777 | 国产精品免费视频久久久 | 天天干天天碰 | 欧美91片 | 欧美老人xxxx18 | 亚洲乱码国产乱码精品天美传媒 | 91精品国产自产91精品 | 久久精品1区 | 中文字幕在线国产精品 | 久久精品免费播放 | 国产黄 | 久久香蕉国产精品麻豆粉嫩av | 国产黄色在线看 | 欧美国产亚洲精品久久久8v | 久久国产精品二国产精品中国洋人 | 久艹在线免费观看 | 免费在线激情视频 | 久久婷亚洲五月一区天天躁 | 黄色软件在线观看 | 天天色天天干天天 | aaawww | 亚洲一区二区三区四区在线视频 | 99精品黄色片免费大全 | 91精品一区二区在线观看 | 一级黄色片在线观看 | 国产91在线免费视频 | 在线97 | 国产精品18久久久久久久久久久久 | 国产视频在线免费 | 激情久久久| 亚洲天堂网在线播放 | 日韩精品久久久 | 国产 av 日韩 | 欧美一级日韩三级 | 九九热.com | 日韩精品大片 | 美女网站黄在线观看 | 91成人精品观看 | 亚洲精品乱码久久久久久蜜桃欧美 | 99久久婷婷国产综合精品 | 人人精品| 中文字幕二区在线观看 | 亚洲91在线| 在线播放av网址 | 日韩av电影免费观看 | 欧美一二在线 | 九九热在线免费观看 | 国偷自产视频一区二区久 | 一区二区三区在线观看中文字幕 | 欧洲精品在线视频 | 肉色欧美久久久久久久免费看 | 在线视频观看成人 | 天天操网站| 丁香六月婷婷综合 | a在线观看免费视频 | 午夜狠狠操 | 欧美一级片免费播放 | 永久免费视频国产 | 色婷婷成人网 | 亚洲电影自拍 | 亚洲精品国产精品国自产 | 欧美日韩在线视频免费 | 中文字幕在线观看视频一区 | 四虎永久精品在线 | aaa日本高清在线播放免费观看 | 午夜电影久久久 | 国产午夜精品视频 | 亚洲国产精品久久久久 | 9在线观看免费高清完整 | 久久91网 | 日韩精品一区二区三区免费观看视频 | 午夜视频一区二区三区 | 狠狠色丁香婷婷综合橹88 | 午夜久久视频 | 亚洲精品高清视频 | 香蕉视频久久久 | 日本美女xx| 九九热精品国产 | 国产盗摄精品一区二区 | 精品国产欧美一区二区三区不卡 | 亚洲 欧美 综合 在线 精品 | 国产视频一区二区在线 | 成人va天堂 | 亚洲成a人片在线观看网站口工 | 国内精品在线观看视频 | 免费男女羞羞的视频网站中文字幕 | 91九色性视频 | 久久一区二区三区日韩 | 精品视频123区在线观看 | 免费的国产精品 | 激情视频网页 | 国产精品久久久久免费观看 | av中文字幕av | 国产一区在线不卡 | 韩日av一区二区 | 三级黄色免费片 | 超碰99人人 | 久久精品视频18 | 国产一区视频在线 | 日韩欧美综合视频 | 4p变态网欧美系列 | 成人视屏免费看 | 91成人精品一区在线播放 | 欧美一区二区三区在线 | 在线观看视频国产一区 | 制服丝袜在线91 | 国产小视频在线播放 | 亚洲伦理电影在线 | 国产综合片 | 91精品婷婷国产综合久久蝌蚪 | 久久综合天天 | 国产成人av网址 | 精品专区一区二区 | 日韩亚洲国产中文字幕 | 五月婷在线播放 | 色五月情| 午夜av剧场| 片黄色毛片黄色毛片 | 尤物97国产精品久久精品国产 | 久久这里只有精品久久 | 午夜美女网站 | 天天操夜夜想 | 亚洲视频免费在线观看 | 狠狠色丁香九九婷婷综合五月 | 久久国产精品99久久久久久丝袜 | 欧美极品在线播放 | 国产手机在线观看视频 | 日韩电影中文字幕在线 | 成人a视频在线观看 | 日韩亚洲精品电影 | 国产91免费在线 | 97超碰资源网 | 黄色网在线免费观看 | 久久经典国产 | 探花视频网站 | 久草影视在线 | 日韩电影中文,亚洲精品乱码 | 色综合天天综合 | 91精品国产91久久久久福利 | 欧美午夜剧场 | 99人久久精品视频最新地址 | 成年一级片 | 久久不卡国产精品一区二区 | 日韩毛片一区 | 日日干美女| 日韩高清免费电影 | 国内免费的中文字幕 | 成人午夜剧场在线观看 | 亚欧日韩成人h片 | 91av在线视频播放 | 91看片淫黄大片在线播放 | 国产精品久久久久久久电影 | 国产成人精品综合久久久 | 免费看片日韩 | 成年人免费看片 | 国产手机在线观看视频 | 免费看的黄色小视频 | 亚洲欧美国产视频 | 欧美午夜性 | 五月婷婷综合激情网 | 亚洲精品国产品国语在线 | 欧美激情第八页 | 日本在线视频一区二区三区 | 日韩免费在线视频观看 | 91精品国产一区二区在线观看 | 国产精品久久久久免费观看 | 在线观看岛国片 | 久草香蕉在线 | 91亚洲精品国偷拍 | 日韩欧美一区二区三区视频 | 日韩一级片大全 | 久久精品精品电影网 | 久久亚洲精品电影 | 亚洲精品av中文字幕在线在线 | 精品黄色片 | 久久久精品久久 | 九九视频在线播放 | www.黄色 | 九色免费视频 | 黄色毛片视频 | 黄色毛片一级 | 国产亚洲精品久久久久久大师 | 免费看三级网站 | 日韩久久午夜一级啪啪 | 国产精品理论片在线观看 | 丁香综合网 | 在线播放视频一区 | 福利区在线观看 | 国产在线91在线电影 | wwwwwww色 | 日韩视频免费播放 | 黄色精品在线看 | 97人人模人人爽人人少妇 | 欧美va天堂va视频va在线 | 99热手机在线| 天天色天天爱天天射综合 | av大片免费在线观看 | 久草久热 | 96精品高清视频在线观看软件特色 | 国产精品久久久久久久久久久久午 | 狠狠狠色丁香综合久久天下网 | 18久久久久| 国产精品综合久久久 | 91九色国产在线 | 欧洲一区二区三区精品 | 国产中文字幕网 | 欧美性精品 | 91日韩精品一区 | 免费性网站 | 91免费日韩 | 欧美另类人妖 | 夜添久久精品亚洲国产精品 | 2023亚洲精品国偷拍自产在线 | 日韩电影中文,亚洲精品乱码 | 国产在线精品国自产拍影院 | 久草视频视频在线播放 | 999视频精品 | 一级黄色免费 | 日韩精品欧美专区 | 不卡av免费在线观看 | 成人久久18免费 | 又长又大又黑又粗欧美 | 欧美一级看片 | 亚洲午夜精品在线观看 | 日韩精品专区在线影院重磅 | 日韩午夜视频在线观看 | www日韩在线| 精品视频免费播放 | 久久五月婷婷丁香社区 | 成人免费ⅴa | 蜜臀av性久久久久蜜臀aⅴ四虎 | 天天操天天射天天操 | 97人人添人澡人人爽超碰动图 | 综合网天天色 | 国产精品美女久久久久久久 | 国产一区二区手机在线观看 | 日韩中文字幕国产 | 天天草网站| 亚洲四虎影院 | 成人av在线网址 | 婷婷国产精品 | 欧美久久久久久久 | 国产一区在线免费 | 色av网站 | 中文字幕一区二区三区视频 | 在线看片中文字幕 | 久九视频| 欧美巨大 | 不卡在线一区 | 欧美日韩亚洲第一 | 黄色软件在线观看 | 免费高清在线观看成人 | 国产亚洲精品久久久久久久久久 | 亚洲精品视频二区 | 亚洲丝袜一区二区 | 成人免费视频视频在线观看 免费 | 国产91精品久久久久久 | 精品国产_亚洲人成在线 | 久草久热 | 91麻豆精品国产91久久久久久 | 国产精品成人久久久久 | 国产专区在线播放 | 在线成人性视频 | 97人人看 | 91视频久久久 | 日韩美一区二区三区 | 91精品国产成人观看 | 视频在线91 | 久草成人在线 | 91麻豆精品国产91久久久使用方法 | 午夜三级在线 | 国产免费午夜 | 9幺看片 | 色婷婷免费视频 | 91久久国产综合精品女同国语 | 伊人永久| 欧美va日韩va | 久久精品观看 | 国产精品 国产精品 | 免费在线观看成人av | 天天搞天天干 | 亚洲精品免费在线观看视频 | 亚洲自拍av在线 | 91久久国产露脸精品国产闺蜜 | 国产不卡在线观看视频 | 操操操人人人 | 日韩av影视 | 人人射av| 欧美另类69 | 欧美a级一区二区 | 500部大龄熟乱视频使用方法 | 国产在线一区二区三区播放 | 免费在线观看一区 | 亚洲国产影院av久久久久 | 黄色av三级在线 | 国产亚洲精品bv在线观看 | 国产成人99av超碰超爽 | 亚洲精品视频在线观看网站 | 欧洲精品久久久久毛片完整版 | 国产黄色一级大片 | a一片一级 | 精品一区二区在线看 | 五月天色丁香 | 国产成人99久久亚洲综合精品 | 国产精品伦一区二区三区视频 | 在线之家免费在线观看电影 | 国产日本三级 | 日韩日韩日韩日韩 | 国产日韩欧美视频 | 网站在线观看你们懂的 | 麻豆传媒视频在线 | 国产精品人成电影在线观看 | 成人免费在线电影 | 亚洲国产mv | 嫩草av影院| 91亚色在线观看 | 天天干天天操av | 久久免费电影网 | 婷婷伊人综合 | 美女久久网站 | 久久久久久久网站 | 精品国产电影一区二区 | 免费看的黄色小视频 | 日韩黄色在线电影 | 欧美日韩久 | 日韩精品一区二区三区在线播放 | 高清av中文在线字幕观看1 | 午夜骚影 | 黄色在线观看免费网站 | www激情com | 久久久久一区二区三区四区 | 久章操| 2024国产精品视频 | 天天综合成人 | 天堂久色| 免费特级黄毛片 | 亚洲成人av片 | 欧美精品在线一区二区 | 国产色在线视频 | 国产资源在线视频 | 九九九九九国产 | 91在线看黄 | 亚洲无吗av| 久久观看最新视频 | a精品视频 | 色综合色综合久久综合频道88 | 国产精品国产毛片 | 国产在线视频一区 | 日本公妇在线观看高清 | 波多野结衣电影一区 | 国产精品久久久免费 | 99久久精品国产一区二区成人 | 亚洲91精品 | 黄色性av | 国产精品女同一区二区三区久久夜 | 奇米网在线观看 | 精品成人网 | 国产精品网在线观看 | 日本韩国中文字幕 | 毛片一区二区 | 国产一线二线三线在线观看 | 中文字幕亚洲综合久久五月天色无吗'' | 中文字幕在线观看第二页 | 日韩综合精品 | 中文字幕精品一区二区精品 | 国产成人精品网站 | 日本精品一二区 | 日韩啪视频 | 国产在线看 | 久草视频在线新免费 | 午夜视频在线观看一区二区三区 | 成人aⅴ视频 | 五月激情婷婷丁香 | 精品成人国产 | 91在线免费视频观看 | 色综合天天综合在线视频 | 国产香蕉97碰碰碰视频在线观看 | 五月激情丁香婷婷 | 国产午夜视频在线观看 | 日韩激情视频在线 | 在线观看a视频 | 91伊人久久大香线蕉蜜芽人口 | 亚洲综合色丁香婷婷六月图片 | 国产高清在线a视频大全 | 欧美在线视频一区二区三区 | 狠狠狠狠狠色综合 | 亚洲成人资源在线观看 | 国产专区视频在线 | 亚州av网站大全 | 在线影视 一区 二区 三区 | 国产在线观看免 | 99热国产在线观看 | 亚洲激情校园春色 | 亚洲天堂网站 | 久久久久久毛片精品免费不卡 | 国产成人一区二区三区影院在线 | 一级精品视频在线观看宜春院 | 婷婷丁香色 | 久色婷婷| 国产中文字幕视频在线观看 | 国产成人福利在线观看 | 91精品啪在线观看国产线免费 | 国产不卡视频在线播放 | 日韩高清一区在线 | 99国产成+人+综合+亚洲 欧美 | 国产糖心vlog在线观看 | 丁香五月亚洲综合在线 | 97av色 | 亚洲精品欧洲精品 | 超碰97.com | 久久在草 | 国产高清av免费在线观看 | 特级西西人体444是什么意思 | 久久精品国产一区二区三 | 中文字幕在线观看av | 色综合久久天天 | www.黄色 | 亚洲性少妇性猛交wwww乱大交 | 午夜国产影院 | 91九色视频网站 | 99精品国产99久久久久久97 | 精品国产乱码久久久久久浪潮 | 综合精品久久 | 91大神在线观看视频 | 久久视频在线观看 | 国产精品免费看久久久8精臀av | 天堂v中文 | 在线播放精品一区二区三区 | 夜夜视频| 成人免费视频免费观看 | 韩国一区视频 | 天天看天天干 | 免费福利片2019潦草影视午夜 | 欧美9999| 又色又爽又黄高潮的免费视频 | 97超级碰| 最近中文国产在线视频 | 中文字幕在线看视频 | 日韩av专区 | 欧美色精品天天在线观看视频 | 国产精品高潮呻吟久久久久 | 黄色在线免费观看网址 | 色视频在线免费 | 91专区在线观看 | 四虎影视成人永久免费观看亚洲欧美 | 激情视频免费观看 | 久久视屏网 | 久久免费毛片视频 | 四虎海外影库www4hu | www.色午夜.com | 亚洲免费av在线播放 | 麻豆视频在线看 | 日本69hd | 97在线成人| 国产精品视频app | 麻豆一精品传二传媒短视频 | 东方av免费在线观看 | 天天爱天天操 |