久久福利_99r_国产日韩在线视频_直接看av的网站_中文欧美日韩_久久一

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Android教你如何發(fā)現(xiàn)APP卡頓的實(shí)現(xiàn)

瀏覽:58日期:2022-09-21 18:26:29

最近部門打算優(yōu)化下 APP 在低端機(jī)上的卡頓情況,既然想優(yōu)化,就必須獲取卡頓情況,那么如何獲取卡頓情況就是本文目的。

一般主線程過(guò)多的 UI 繪制、大量的 IO 操作或是大量的計(jì)算操作占用 CPU,導(dǎo)致 App 界面卡頓。只要我們能在發(fā)生卡頓的時(shí)候,捕捉到主線程的堆棧信息和系統(tǒng)的資源使用信息,即可準(zhǔn)確分析卡頓發(fā)生在什么函數(shù),資源占用情況如何。那么問題就是如何有效檢測(cè) Android 主線程的卡頓發(fā)生?

用 adb 系統(tǒng)工具觀察 App 的卡頓數(shù)據(jù)情況,試圖重現(xiàn)場(chǎng)景來(lái)定位問題。

常用的方式是使用 adb SurfaceFlinger 服務(wù)和 adb gfxinfo 功能,在自動(dòng)化操作 app 的過(guò)程中,使用 adb 獲取數(shù)據(jù)來(lái)監(jiān)控 app 的流暢情況,發(fā)現(xiàn)出現(xiàn)出現(xiàn)卡頓的時(shí)間段,尋找出現(xiàn)卡頓的場(chǎng)景和操作。

方式1:adb shell dumpsysSurfaceFlinger

使用 ‘a(chǎn)db shell dumpsysSurfaceFlinger’ 命令即可獲取最近 127 幀的數(shù)據(jù),通過(guò)定期執(zhí)行 adb 命令,獲取幀數(shù)來(lái)計(jì)算出幀率 FPS。

方式2:adb shell dumpsys gfxinfo

使用 ‘a(chǎn)db shell dumpsys gfxinfo’ 命令即可獲取最新 128 幀的繪制信息,詳細(xì)包括每一幀繪制的 Draw,Process,Execute 三個(gè)過(guò)程的耗時(shí),如果這三個(gè)時(shí)間總和超過(guò) 16.6ms 即認(rèn)為是發(fā)生了卡頓。

已有的兩種方案比較適合衡量回歸卡頓問題的修復(fù)效果和判斷某些特定場(chǎng)景下是否有卡頓情況,然而,這樣的方式有幾個(gè)明顯的不足:

一般很難構(gòu)造實(shí)際用戶卡頓的環(huán)境來(lái)重現(xiàn); 這種方式操作起來(lái)比較麻煩,需編寫自動(dòng)化用例,無(wú)法覆蓋大量的可疑場(chǎng)景,測(cè)試重現(xiàn)耗時(shí)耗人力; 無(wú)法衡量靜態(tài)頁(yè)面的卡頓情況; 出現(xiàn)卡頓的時(shí)候app無(wú)法及時(shí)獲取運(yùn)行狀態(tài)和信息,開發(fā)定位困難。

隨著對(duì)Android 源碼的深入研究,也有了其他兩種比較方便的方式,并且這兩種方式侵入性小,占用內(nèi)存低,能夠更好的用在實(shí)際場(chǎng)景中:

利用UI線程的Looper打印的日志匹配; 使用Choreographer.FrameCallback

利用 UI 線程的 Looper 打印的日志匹配

Android 主線程更新 UI。如果界面1秒鐘刷新少于 60 次,即 FPS 小于 60,用戶就會(huì)產(chǎn)生卡頓感覺。簡(jiǎn)單來(lái)說(shuō),Android 使用消息機(jī)制進(jìn)行 UI 更新,UI 線程有個(gè) Looper,在其 loop方法中會(huì)不斷取出 message,調(diào)用其綁定的 Handler 在 UI 線程執(zhí)行。如果在 handler 的 dispatchMesaage 方法里有耗時(shí)操作,就會(huì)發(fā)生卡頓。

下面來(lái)看下 Looper.loop( ) 的源碼

public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException('No Looper; Looper.prepare() wasn’t called on this thread.'); } final MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); // Allow overriding a threshold with a system prop. e.g. // adb shell ’setprop log.looper.1000.main.slow 1 && stop && start’ final int thresholdOverride =SystemProperties.getInt('log.looper.' + Process.myUid() + '.' + Thread.currentThread().getName() + '.slow', 0); boolean slowDeliveryDetected = false; for (;;) { Message msg = queue.next(); // might block if (msg == null) {// No message indicates that the message queue is quitting.return; } // This must be in a local variable, in case a UI event sets the logger final Printer logging = me.mLogging; if (logging != null) {logging.println('>>>>> Dispatching to ' + msg.target + ' ' + msg.callback + ': ' + msg.what); } // Make sure the observer won’t change while processing a transaction. final Observer observer = sObserver; final long traceTag = me.mTraceTag; long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs; long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs; if (thresholdOverride > 0) {slowDispatchThresholdMs = thresholdOverride;slowDeliveryThresholdMs = thresholdOverride; } final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0); final boolean logSlowDispatch = (slowDispatchThresholdMs > 0); final boolean needStartTime = logSlowDelivery || logSlowDispatch; final boolean needEndTime = logSlowDispatch; if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0; final long dispatchEnd; Object token = null; if (observer != null) {token = observer.messageDispatchStarting(); } long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid); try {msg.target.dispatchMessage(msg);if (observer != null) { observer.messageDispatched(token, msg);}dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0; } catch (Exception exception) {if (observer != null) { observer.dispatchingThrewException(token, msg, exception);}throw exception; } finally {ThreadLocalWorkSource.restore(origWorkSource);if (traceTag != 0) { Trace.traceEnd(traceTag);} } if (logSlowDelivery) {if (slowDeliveryDetected) { if ((dispatchStart - msg.when) <= 10) { Slog.w(TAG, 'Drained'); slowDeliveryDetected = false; }} else { if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, 'delivery', msg)) { // Once we write a slow delivery log, suppress until the queue drains. slowDeliveryDetected = true; }} } if (logSlowDispatch) {showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, 'dispatch', msg); } if (logging != null) {logging.println('<<<<< Finished to ' + msg.target + ' ' + msg.callback); } // Make sure that during the course of dispatching the // identity of the thread wasn’t corrupted. final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) {Log.wtf(TAG, 'Thread identity changed from 0x' + Long.toHexString(ident) + ' to 0x' + Long.toHexString(newIdent) + ' while dispatching to ' + msg.target.getClass().getName() + ' ' + msg.callback + ' what=' + msg.what); } msg.recycleUnchecked(); } }

代碼中兩處標(biāo)紅的地方,就是 msg.target.dispatchMessage(msg) 的執(zhí)行前后索打印的 log。通過(guò)測(cè)量處理時(shí)間就能檢測(cè)到部分UI線程是否有耗時(shí)的操作。注意到這行執(zhí)行代碼的前后,有兩個(gè) logging.println 函數(shù),如果設(shè)置了logging,會(huì)分別打印出 ”>>>>> Dispatching to “ 和 ”<<<<< Finished to “ 這樣的日志,這樣我們就可以通過(guò)兩次log的時(shí)間差值,來(lái)計(jì)算 dispatchMessage 的執(zhí)行時(shí)間,從而設(shè)置閾值判斷是否發(fā)生了卡頓。

那么如何設(shè)置 logging 呢?

我們看下面的代碼:

/** * Control logging of messages as they are processed by this Looper. If * enabled, a log message will be written to <var>printer</var> * at the beginning and ending of each message dispatch, identifying the * target Handler and message contents. * * @param printer A Printer object that will receive log messages, or * null to disable message logging. */public final class Looper { private Printer mLogging; public void setMessageLogging(@Nullable Printer printer) { mLogging = printer; } } public interface Printer { void println(String x); }

Looper 的 mLogging 是私有的,并且提供了 setMessageLogging(@Nullable Printer printer) 方法,所以我們可以自己實(shí)現(xiàn)一個(gè) Printer,在通過(guò) setMessageLogging() 方法傳入即可,代碼如下:

public class BlockDetectByPrinter { public static void start() { Looper.getMainLooper().setMessageLogging(new Printer() { private static final String START = '>>>>> Dispatching'; private static final String END = '<<<<< Finished'; @Override public void println(String x) {if (x.startsWith(START)) { LogMonitor.getInstance().startMonitor();}if (x.startsWith(END)) { LogMonitor.getInstance().removeMonitor();} } }); }}

設(shè)置了logging后,loop方法會(huì)回調(diào) logging.println 打印出每次消息執(zhí)行的時(shí)間日志:”>>>>> Dispatching to “和”<<<<< Finished to “。BlockDetectByPrinter 的使用則在Application 的 onCreate 方法中調(diào)用 BlockDetectByPrinter.start() 即可。

我們可以簡(jiǎn)單實(shí)現(xiàn)一個(gè) LogMonitor 來(lái)記錄卡頓時(shí)候主線程的堆棧信息。當(dāng)匹配到 >>>>> Dispatching 時(shí),執(zhí)行 startMonitor,會(huì)在 200ms(設(shè)定的卡頓閾值)后執(zhí)行任務(wù),這個(gè)任務(wù)負(fù)責(zé)在子線程(非UI線程)打印UI線程的堆棧信息。如果消息低于 200ms 內(nèi)執(zhí)行完成,就可以匹配到 <<<<< Finished 日志,那么在打印堆棧任務(wù)啟動(dòng)前執(zhí)行 removeMonitor 取消了這個(gè)任務(wù),則認(rèn)為沒有卡頓的發(fā)生;如果消息超過(guò) 200ms 才執(zhí)行完畢,此時(shí)認(rèn)為發(fā)生了卡頓,并打印 UI 線程的堆棧信息。

LogMonitor如何實(shí)現(xiàn)?

public class LogMonitor { private static final String TAG = 'LogMonitor'; private static LogMonitor sInstance = new LogMonitor(); private HandlerThread mLogThread = new HandlerThread('log'); private Handler mIoHandler; private static final long TIME_BLOCK = 200L; private LogMonitor() { mLogThread.start(); mIoHandler = new Handler(mLogThread.getLooper()); } private static Runnable mLogRunnable = new Runnable() { @Override public void run() { StringBuilder sb = new StringBuilder(); StackTraceElement[] stackTrace = Looper.getMainLooper().getThread().getStackTrace(); for (StackTraceElement s : stackTrace) {sb.append(s.toString() + 'n'); } Log.e(TAG, sb.toString()); } }; public static LogMonitor getInstance() { return sInstance; } public boolean isMonitor() { return mIoHandler.hasCallbacks(mLogRunnable); } public void startMonitor() { mIoHandler.postDelayed(mLogRunnable, TIME_BLOCK); } public void removeMonitor() { mIoHandler.removeCallbacks(mLogRunnable); }}

這里我們使用 HandlerThread 來(lái)構(gòu)造一個(gè) Handler,HandlerThread 繼承自 Thread,實(shí)際上就一個(gè) Thread,只不過(guò)比普通的 Thread 多了一個(gè) Looper,對(duì)外提供自己這個(gè) Looper 對(duì)象的 getLooper 方法,然后創(chuàng)建 Handler 時(shí)將 HandlerThread 中的 looper 對(duì)象傳入。這樣我們的 mIoHandler 對(duì)象就是與 HandlerThread 這個(gè)非 UI 線程綁定的了,它處理耗時(shí)操作將不會(huì)阻塞UI。如果UI線程阻塞超過(guò) 200ms,就會(huì)在子線程中執(zhí)行 mLogRunnable,打印出 UI 線程當(dāng)前的堆棧信息,如果處理消息沒有超過(guò) 1000ms,則會(huì)實(shí)時(shí)的 remove 掉這個(gè)mLogRunnable 任務(wù)。

發(fā)生卡頓時(shí)打印出堆棧信息的大致內(nèi)容如下,開發(fā)可以通過(guò) log 定位耗時(shí)的地方。

2020-10-30 14:26:13.823 30359-30415/com.example.myproxyplugin E/LogMonitor: java.lang.Thread.sleep(Native Method) java.lang.Thread.sleep(Thread.java:443) java.lang.Thread.sleep(Thread.java:359) com.example.myproxyplugin.MainActivity$1.run(MainActivity.java:22) android.os.Handler.handleCallback(Handler.java:900) android.os.Handler.dispatchMessage(Handler.java:103) android.os.Looper.loop(Looper.java:219) android.app.ActivityThread.main(ActivityThread.java:8347) java.lang.reflect.Method.invoke(Native Method) com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)

優(yōu)點(diǎn):用戶使用 app 或者測(cè)試過(guò)程中都能從app層面來(lái)監(jiān)控卡頓情況,一旦出現(xiàn)卡頓能記錄 app 狀態(tài)和信息, 只要dispatchMesaage執(zhí)行耗時(shí)過(guò)大都會(huì)記錄下來(lái),不再有前面兩種adb方式面臨的問題與不足。

缺點(diǎn):需另開子線程獲取堆棧信息,會(huì)消耗少量系統(tǒng)資源。

在實(shí)際實(shí)現(xiàn)中,不同手機(jī)不同 Android 系統(tǒng)甚至是不同的 ROM 版本,Loop 函數(shù)不一定都能打印出 ”>>>>> Dispatching to “ 和 ”<<<<< Finished to “ 這樣的日志,導(dǎo)致該方式無(wú)法進(jìn)行。

優(yōu)化的策略:我們知道 Loop 函數(shù)開始和結(jié)束必會(huì)執(zhí)行 println 打印日志,所以優(yōu)化版本將卡頓的判斷改為,Loop輸出第一句 log 時(shí)當(dāng)作 startMonitor,輸出下一句log時(shí)當(dāng)作end時(shí)刻來(lái)解決這個(gè)問題。

其實(shí) Looper 中有個(gè) Observer 接口可以很好的完成這個(gè)任務(wù),只是因?yàn)楸粯?biāo)記為 hide 了,所以我們不能使用,不過(guò)可以知道下。

Observer 接口提供了三個(gè)方法,分別是監(jiān)聽任務(wù)開始,結(jié)束,發(fā)生錯(cuò)誤的回調(diào)。

/** {@hide} */ public interface Observer { /** * Called right before a message is dispatched. * * <p> The token type is not specified to allow the implementation to specify its own type. * * @return a token used for collecting telemetry when dispatching a single message. * The token token must be passed back exactly once to either * {@link Observer#messageDispatched} or {@link Observer#dispatchingThrewException} * and must not be reused again. * */ Object messageDispatchStarting(); /** * Called when a message was processed by a Handler. * * @param token Token obtained by previously calling * {@link Observer#messageDispatchStarting} on the same Observer instance. * @param msg The message that was dispatched. */ void messageDispatched(Object token, Message msg); /** * Called when an exception was thrown while processing a message. * * @param token Token obtained by previously calling * {@link Observer#messageDispatchStarting} on the same Observer instance. * @param msg The message that was dispatched and caused an exception. * @param exception The exception that was thrown. */ void dispatchingThrewException(Object token, Message msg, Exception exception); }

利用Choreographer.FrameCallback監(jiān)控卡頓

Choreographer.FrameCallback 官方文檔鏈接(https://developer.android.com/reference/android/view/Choreographer.FrameCallback.html)

我們知道, Android 系統(tǒng)每隔 16ms 發(fā)出 VSYNC 信號(hào),來(lái)通知界面進(jìn)行重繪、渲染,每一次同步的周期為16.6ms,代表一幀的刷新頻率。SDK 中包含了一個(gè)相關(guān)類,以及相關(guān)回調(diào)。理論上來(lái)說(shuō)兩次回調(diào)的時(shí)間周期應(yīng)該在 16ms,如果超過(guò)了 16ms 我們則認(rèn)為發(fā)生了卡頓,利用兩次回調(diào)間的時(shí)間周期來(lái)判斷是否發(fā)生卡頓(這個(gè)方案是 Android 4.1 API 16 以上才支持)。

這個(gè)方案的原理主要是通過(guò) Choreographer 類設(shè)置它的 FrameCallback 函數(shù),當(dāng)每一幀被渲染時(shí)會(huì)觸發(fā)回調(diào) FrameCallback, FrameCallback 回調(diào) void doFrame (long frameTimeNanos) 函數(shù)。一次界面渲染會(huì)回調(diào) doFrame 方法,如果兩次 doFrame 之間的間隔大于 16.6ms 說(shuō)明發(fā)生了卡頓。

public class FPSFrameCallback implements Choreographer.FrameCallback { private static final String TAG = 'FPS_TEST'; private long mLastFrameTimeNanos = 0; private long mFrameIntervalNanos; public FPSFrameCallback(long lastFrameTimeNanos) { mLastFrameTimeNanos = lastFrameTimeNanos; // 1s 60 幀 mFrameIntervalNanos = (long) (1000000000 / 60.0); } @Override public void doFrame(long frameTimeNanos) { //初始化時(shí)間 if (mLastFrameTimeNanos == 0) { mLastFrameTimeNanos = frameTimeNanos; } final long jitterNanos = frameTimeNanos - mLastFrameTimeNanos; if (jitterNanos >= mFrameIntervalNanos) { final long skippedFrames = jitterNanos / mFrameIntervalNanos; if (skippedFrames > 30) {Log.i(TAG, 'Skipped ' + skippedFrames + ' frames! ' + 'The application may be doing too much work on its main thread.'); } } mLastFrameTimeNanos = frameTimeNanos; //注冊(cè)下一幀回調(diào) Choreographer.getInstance().postFrameCallback(this); }}

本質(zhì)和 log 沒太多區(qū)別,但是這個(gè)更加通用些,不會(huì)因?yàn)闄C(jī)型系統(tǒng)原因出現(xiàn)不可用的問題。

示例

下面進(jìn)入實(shí)戰(zhàn),看看代碼層面是如何實(shí)現(xiàn)的。

MainActivity 代碼如下:

public class MainActivity extends AppCompatActivity { Handler handler = new Handler(Looper.getMainLooper()); private final Runnable runnable = new Runnable() { @Override public void run() { try {Thread.sleep(600);handler.postDelayed(runnable, 500); } catch (InterruptedException e) {e.printStackTrace(); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Choreographer.getInstance().postFrameCallback(new FPSFrameCallback(System.nanoTime())); BlockDetectByPrinter.start(); } @Override protected void onResume() { super.onResume(); handler.postDelayed(runnable, 500); }}

收集到的堆棧信息如下:

2020-10-30 14:26:13.823 30359-30415/com.example.myproxyplugin E/LogMonitor: java.lang.Thread.sleep(Native Method) java.lang.Thread.sleep(Thread.java:443) java.lang.Thread.sleep(Thread.java:359) com.example.myproxyplugin.MainActivity$1.run(MainActivity.java:22) android.os.Handler.handleCallback(Handler.java:900) android.os.Handler.dispatchMessage(Handler.java:103) android.os.Looper.loop(Looper.java:219) android.app.ActivityThread.main(ActivityThread.java:8347) java.lang.reflect.Method.invoke(Native Method) com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)

對(duì)于 FPS log 可以看到如下信息:

I/Choreographer: Skipped 64 frames! The application may be doing too much work on its main thread. I/FPS_TEST: Skipped 65 frames! The application may be doing too much work on its main thread.

如果你要把上面的方法用到自己的APP 中,那么還需要很多操作,具體可以閱讀參考文獻(xiàn)的內(nèi)容。

參考文章

廣研Android卡頓監(jiān)控系統(tǒng)

到此這篇關(guān)于Android教你如何發(fā)現(xiàn)APP卡頓的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Android APP卡頓內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Android
相關(guān)文章:
主站蜘蛛池模板: 国产高清精品一区二区三区 | 午夜精品久久久 | 7799精品视频天天看 | 亚洲欧美一区二区三区在线 | 国产成人一区 | 久草视频在线播放 | 国产欧美日韩综合精品 | 日韩图区| 国产精品亚洲视频 | 日韩精品一区二区三区第95 | 国产精品美乳一区二区免费 | 日本三级做a全过程在线观看 | 欧美精品一区二区三区手机在线 | 免费观看成人性生生活片 | 日韩免费av一区二区 | 毛片真人毛毛片毛片 | 亚洲视频在线视频 | 人人玩人人添人人澡97 | 久久久久久亚洲一区二区三区蜜臀 | 国产一区二区av | 一级视频在线观看 | 久久91精品国产 | 一级片在线播放 | 日韩日韩| 精品久久久久久国产 | 97av| 狠狠搞狠狠搞 | 国产精品久久久久久久久久三级 | 久久亚洲一区二区三区四区五区高 | 久久99国产精品久久99大师 | 精品欧美乱码久久久久久1区2区 | 久久亚洲精品中文字幕 | 99视频精品 | 亚洲激情一区二区 | 欧美日韩国产在线 | 欧美欧美欧美 | 久久这里只有国产精品 | 国产欧美在线观看 | 欧美亚洲91 | 国产激情性色视频在线观看 | 精品视频一区二区三区 | 国产乱码精品一区二区三区忘忧草 | 欧美日韩在线播放 | 日韩免费| 欧美黑人狂躁日本寡妇 | 色婷婷综合网 | 午夜精品久久久久久99热软件 | 久综合网 | 在线观看精品视频网站 | 日韩精品一区二区三区中文字幕 | 亚洲综合欧美 | 理论片91 | 男人视频网站 | 午夜精品福利在线观看 | 男人的天堂在线视频 | 国产福利视频 | 一区二区视频 | 精国产品一区二区三区 | 91在线视频播放 | 色性网站 | 欧美三级视频 | 九色视频网站 | 亚洲小视频 | 中文精品在线 | 久久久99精品免费观看 | 国产精品久久久久久影院8一贰佰 | 国产精品高潮呻吟 | 亚洲精品中文字幕在线观看 | 欧美一区二区三区黄 | 色性网| 亚洲香蕉视频 | 欧美日韩亚洲国产综合 | 中文字幕第一页在线 | 欧美久久久| 在线观看亚洲精品 | 国产在线小视频 | 精品在线视频一区 | 久久精品黄 | 一区二区在线视频 | 久日精品 | 亚洲一区中文字幕 | 亚洲一区视频在线 | 国产老女人精品毛片久久 | 亚洲一区二区三区四区五区中文 | 国产精品久久视频 | 国产一区二区精品在线观看 | 中文字幕亚洲一区二区三区 | 一区二区亚洲 | 久久久久久久久久久久久久久久久久久 | 天天干天天摸 | 精品久久中文字幕 | 成人午夜免费网站 | 午夜私人影院在线观看 | 国产综合视频在线观看 | 三级特黄特色视频 | 日韩国产一区二区三区 | 在线日韩成人 | 一区二区三区不卡视频 | 亚洲国产精品自拍 | 午夜激情视频免费 | 国产在线精品一区 | 国产一区二区三区在线视频 | 狠狠搞狠狠操 | 欧美日韩一区二区三区在线观看 | 毛片入口 | 国产精品久久久久久久久久新婚 | 日韩av高清在线 | 美女在线一区 | 国产欧美日韩一区二区三区 | 精品国产一区二区在线 | 精品一区二区久久久久久久网站 | 一区二区三区 在线 | 久久午夜精品 | 久久久精品网 | 欧美精品久久久久久久久久丰满 | 成人精品免费视频 | 国产综合亚洲精品一区二 | 成人国产免费视频 | 羞羞视频网站在线免费观看 | 日韩欧美不卡 | 毛片在线视频 | 亚洲成人精品在线 | 欧美一级成人欧美性视频播放 | 亚洲高清在线观看 | 婷婷激情在线 | 亚洲欧美日韩在线一区二区三区 | 在线免费黄色小视频 | 日韩一区久久 | 一区二区日韩精品 | av天空| 夜久久| 在线色综合 | 国产精品国产精品国产专区不片 | 精品91久久久 | 蜜月久久99静品久久久久久 | 欧美夜夜爽 | 久久精品久久久 | 综合网日韩| 国产精品久久精品久久 | 成人a视频 | 超级碰在线| 老司机福利在线视频 | 久久久www成人免费精品 | 97国产精品视频 | 涩涩视频大全 | 久久久精品日本 | av福利在线观看 | 国产精品18 | 天天干天天搞天天射 | 羞羞视频在线观看视频 | 人妖天堂狠狠ts人妖天堂狠狠 | 亚洲国产精品综合久久久 | 国产精品日本欧美一区二区三区 | 亚洲激情av | 国产精品亚洲第一 | 国产精品久久久麻豆 | 亚洲成人精品在线观看 | 日韩在线欧美 | 中文字幕天堂在线 | 欧美日韩啪啪 | 国产精品视频久久久 | 婷婷色在线 | 色综合99| 麻豆乱码国产一区二区三区 | 日韩在线免费视频 | 久久e久久| 亚洲国产精品一区 | 成人在线观 | 一区二区在线 | 九九热这里只有精品8 | 日韩欧美在线视频 | 午夜看片| 国产一区二区精品在线观看 | 成人免费看| 中文字幕日韩av | 精品亚洲成a人片在线观看 国产高清在线 | 亚洲不卡视频 | 97精品超碰一区二区三区 | 看免费毛片 | 亚洲热妇| 免费99精品国产自在在线 | 国产精品一区二区三区四区 | 久久久久国产 | 美女在线一区 | 99色资源 | 亚洲精品久久一区二区三区 | 精国产品一区二区三区 | 一区视频在线 | 国产精品国色综合久久 | 日韩一区二区三区在线视频 | 青娱乐国产精品视频 | 国产偷久久9977 | 91一区二区三区久久国产乱 | 欧美日韩国产一区二区三区 | 国产精品久久久久久久久 | 久久草视频 | 很黄很色很爽的视频 | 国产一区二区三区四区三区 | 免费一区二区 | cao视频| 奇米影视77 | 中文字幕亚洲欧美日韩在线不卡 | 毛片大全 | 日韩超级大片免费看国产国产播放器 | 亚州成人| 亚洲福利二区 | 青青草亚洲 | 国产视频精品自拍 | 99久久电影 | 免费的色网站 | 欧美不卡| 国内外成人在线视频 | 国产成人看片 | 免费黄色网址在线播放 | 久久人人爽人人爽 | 国产亚洲综合一区二区 | 国产最好的精华液网站 | 亚洲一区二区在线视频 | 国产成人综合视频 | 精品久久久久久久久久久 | 国产情侣一区二区三区 | 午夜影院a | www.国产91 | 国产成人久久精品一区二区三区 | 中文字幕第一页在线 | 亚洲国产午夜视频 | 嫩草最新网址 | 久久国产精品99久久久久久牛牛 | 福利网址 | 成av在线| 精品国产成人 | 免费精品| 久久九九精品视频 | 国产免费av在线 | 日韩不卡av | 欧美黑人一级爽快片淫片高清 | 91精品国产91久久久久久吃药 | 91精品久久久久久久久久 | 国产二区视频 | 国产资源在线观看 | 超碰首页 | 中文字幕亚洲在线 | 国产精品亚欧美一区二区 | 国产欧美在线播放 | 日韩精品一区二区三区免费观看视频 | 国产精品成av人在线视午夜片 | 久久精品国产一区二区三区不卡 | 黄色一级视频 | 欧美一级免费 | 欧美一区二区三区男人的天堂 | 亚洲成人网一区 | 欧美1314 | 理论黄色片 | 国产区在线 | 午夜影院入口 | 国产一区二区三区网站 | 久草热8精品视频在线观看 黄色片网站视频 | 97视频观看 | 成年人网站在线免费看 | 欧美一级黄色网 | 精品久久久久香蕉网 | 亚洲精品91 | 手机看片169| 国产成人av一区 | 黄在线免费观看 | 男女视频在线 | 国产精品影院在线观看 | 色小妹一二三区 | 日韩成人免费电影 | 一级免费视频 | 91久久夜色精品国产网站 | 久久精品国产99国产 | 九色av | 91看片淫黄大片一级在线观看 | 成人不卡 | 精品国产乱码久久久久久1区2区 | 日韩视频在线免费观看 | 色婷婷综合网 | 81精品国产乱码久久久久久 | 欧美精品a∨在线观看不卡 欧美日韩中文字幕在线播放 | 国产精品不卡 | 亚洲区在线| 精品无码久久久久国产 | 91精品国产九九九久久久亚洲 | 免费观看在线午夜影视 | 男女黄色免费网站 | 不卡一区二区三区四区 | 九草av| 国产精品乱码一二三区的特点 | 99精品欧美一区二区蜜桃免费 | 日韩av免费看 | 久久免费国产 | 涩涩视频在线看 | 懂色一区二区三区av片 | 日本久久精品视频 | 免费观看h视频 | 亚洲视频中文字幕 | 国产色在线 | 免费黄色电影在线观看 | 黄色在线免费观看 | 成人在线免费 | 国产精品美女久久久久久不卡 | 欧美中文在线 | 狠狠躁夜夜躁人人爽天天高潮 | 高清国产午夜精品久久久久久 | 欧美国产在线观看 | 在线观看国产视频 | 精品国产一区二区 | 国产精品片aa在线观看 | 国产精品视频一区二区三区四蜜臂 | 亚洲激情在线 | 国产视频三区 | 亚洲成人精品一区 | 亚洲骚片 | 日韩精品一区二区三区中文字幕 | 91精品国产一区二区三区香蕉 | 91精品久久久久久久久久久久久久久 | 欧美日本免费一区二区三区 | jlzzjlzz亚洲日本少妇 | 精品国模一区二区三区欧美 | 99精品欧美一区二区三区 | 伊人爱爱网 | 99小视频| 国产一区二区在线视频 | 九九免费视频 | 日韩欧美国产精品 | 日本 欧美 国产 | 精品久久久99 | 亚洲一区电影 | 99re在线视频 | 操碰97| 国产欧美日韩在线观看 | 在线观看亚洲一区二区 | h网站在线观看 | 免费成人av在线 | 免费国产视频 | 欧美在线视频网 | 国产日韩欧美精品一区二区三区 | 羞羞视频在线播放 | 亚洲经典视频在线观看 | a在线看| 午夜国产精品视频 | 国外成人在线视频网站 | 国产精品中文字幕在线播放 | 日韩欧美国产一区二区三区 | 久久久久亚洲 | 中国一级毛片免费 | 中文字幕在线一区二区三区 | 欧美久久视频 | 另类二区 | 中文字幕乱码亚洲精品一区 | 自拍视频免费 | 91精品综合久久久久久五月天 | 亚洲精品影院 | 国产三级在线免费观看 | 韩日精品在线观看 | 一区二区三区中文字幕 | 日韩欧美在线视频免费观看 | 亚洲人成人一区二区在线观看 | 国产99久久久国产精品 | 午夜免费在线 | 成人在线精品 | 综合一区二区三区 | 一区二区三区四区视频 | 欧美专区在线观看 | 欧美日韩精品一区二区 | 国产香蕉视频在线播放 | 久久综合九色综合欧美狠狠 | 国产一级免费在线观看 | 欧美精品黄 | 亚洲精品视频在线观看网站 | 欧美午夜精品久久久久久人妖 | 欧美国产日韩一区 | 国产欧美精品一区二区三区 | 一区二区三区欧美 | 亚洲精品国产a久久久久久 国产毛片毛片 | 午夜免费影视 | 一区二区亚洲 | 天天射美女 | 成人亚洲一区 | 精产国产伦理一二三区 | 蜜桃免费一区二区三区 | 日本一区二区不卡 | 久久com| 国产精品www| 国产毛片网站 | 欧美黑人xxx| 久久大 | 成人国产 | 久久免费在线观看 | 精品国产乱码久久久久久蜜柚 | 精品久久久久久久人人人人传媒 | 亚洲欧美日韩另类精品一区二区三区 | 一卡二卡久久 | 亚洲综合福利视频 | 欧洲成人午夜免费大片 | 欧美一级爆毛片 | 91精品国产欧美一区二区成人 | 九九亚洲 | 亚洲精品成人 | 久热精品在线 | 爱草在线 | 免费亚洲成人 | 久久99精品国产91久久来源 | 黄色一级在线播放 | 久久9国产偷伦 | 日韩在线成人 | 久久综合久久综合久久综合 | 国产一区二区精品 | 99久久婷婷国产综合精品电影 | 久久青 | 99视频这里有精品 | 污视频在线观看免费 | 视频精品一区二区 | 欧美成人黄色 | 91免费看 | 91麻豆视频| 天天干狠狠干 | 欧美日韩视频在线第一区 | 亚洲精品成人无限看 | 欧美一区二区免费 | 欧美精品一区二区三区视频 | 在线视频一区二区三区 | 亚洲成人免费视频在线观看 | 欧美一区| 亚洲日韩中文字幕一区 | 欧美成人免费在线视频 | 97免费在线视频 | 一级毛片大全免费播放 | 天天碰天天操 | 亚洲精品在线播放 | 亚洲一区二区三区久久 | 在线观看中文 | 亚洲第一成年免费网站 | 亚洲成人在线网站 | 午夜免费 | 在线免费观看成年人视频 | 日韩欧美在线看 | 久久久久久免费看 | 91精品国产综合久久久久久丝袜 | 亚洲欧美日韩精品久久亚洲区 | 搜索黄色毛片 | 在线日韩视频 | 四色成人av永久网址 | 中国一级免费毛片 | 羞羞视频在线观看入口 | 欧美三级在线 | 91中文在线观看 | 国产日皮视频 | 国产精一区二区 | 久久亚洲精品国产一区 | 国产九九九 | 欧美久久一区二区 | av一级在线| 精品无码久久久久国产 | 中文字幕不卡 | 亚洲性生活免费视频 | 欧美 日韩 在线播放 | 欧美日韩免费一区二区三区 | 精品视频久久 | 日韩高清中文字幕 | 极品videossex中国妞hd | 欧美日韩国产一区二区 | 精品国产一区二区三区不卡蜜臂 | 成人a级网站 | 日本高清精品 | 成人欧美| 亚洲一区视频在线 | 久草综合在线 | 欧美一区二区久久久 | 美女福利视频 | 午夜色电影 | 亚洲人人 | 成人久久久久久久久 | 国模一区二区三区 | 开操网| 欧美一级黄色大片 | 久久免费国产精品 | 欧美一级在线观看 | 91精品国产综合久久久久久漫画 | 色综合激情 | 国产在线观看一区二区三区 | 人人鲁人人莫一区二区三区 | 久久机热 | a免费网站| 一级激情片 | 成人不卡视频 | 成人a在线视频免费观看 | 亚洲九九 | 久久久久久免费毛片精品 | 午夜视频一区 | 一区二区影院 | 日韩国产| 91视频一88av | 亚洲一区二区免费看 | 欧美 日韩| 亚洲欧美一区二区三区在线 | 欧美日韩国产在线播放 | 久久国产一区 | 特级生活片 | 国产日韩精品一区二区 | 精品久久久久久久久久久久 | 天天插天天操 | 日韩av在线不卡 | 欧美午夜在线 | 国产三级电影 | 国产视频二 | 精品在线视频观看 | 国产在线观看一区二区 | 久一在线| 欧美精品91 | 欧美激情综合色综合啪啪五月 | 视频国产一区 | 国产日韩欧美综合 | 欧美a v在线播放 | 国产精品久久久久久久久免费 | 国产馆一区二区 | 欧美人成在线观看 | 国产精品精品视频一区二区三区 | 黄色网页在线观看 | 欧美精品黄色 | 日韩欧美a级v片免费播放 | 欧美一级精品片在线看 | 国产区在线 | 久久精品欧美 | 日韩免费高清视频 | 亚洲美女在线视频 | 日韩在线中文字幕 | 欧美激情国产日韩精品一区18 | www一区| 狠狠干狠狠干 | 一级毛片免费一级 | 久在线视频 | 91夜夜蜜桃臀一区二区三区 | 国产视频精品在线观看 | 日韩一区二区在线观看 | 黄色网址大全在线观看 | 干干干操操操 | 老司机福利在线视频 | 午夜亚洲电影 | 一区二区三区视频 | 美女国产精品 | 久久一区二区视频 | 午夜久久网站 | 国产精品美女久久久久久免费 | 国产精品视频区 | 君岛美绪一区二区三区 | 青青草在线免费视频 | 四虎影院网站 | 免费的污网站 | 日韩毛片免费在线观看 | 欧美精品久久久久久久久久丰满 | 1204国产成人精品视频 | 色天天综合久久久久综合片 | 色婷婷综合网 | 黄色片免费看 | 91免费观看 | 亚洲精品久久久久久久久久久久久 | 男人的天堂在线视频 | 国产伦精品一区二区三区四区视频 | 国产高清久久 | 欧美视频一区二区 | 91视在线国内在线播放酒店 | 成人av观看 | 国产丝袜一区 | 老牛嫩草一区二区三区眼镜 | 国产精品自产av一区二区三区 | 国产目拍亚洲精品99久久精品 | 日韩在线一区二区 | 欧美白人做受xxxx视频 | 久久这里精品 | 精品久久久久久久久久 | www视频在线观看 | www中文字幕 | 国产成人在线播放 | 免费成人在线网站 | 亚洲免费看片 | 久久精品视频一区 | 在线观看免费av的网址 | 欧美日韩免费一区二区三区 | 中文字幕在线电影观看 | 亚洲欧美日韩在线 | 精品久久久久久久 | 人人种亚洲 | 亚洲欧洲日本国产 | 看片国产 | 亚洲精品久久久一区二区三区 | 久久99国产精品久久99果冻传媒 | 欧美日韩精品在线观看 | 日本在线观看 | 成人一级片 | 国产aⅴ一区二区 | 久久久久久久国产精品 | 日韩中文字幕国产 | 男人av网 | 色综久久 | 久久精品久久久久久久久久久久久 | 日韩三级在线免费观看 | 久久精品国产一区二区三区不卡 | 香蕉久久久| 色综合久久久久 | 亚洲成人基地 | 超碰在线99 | 羞羞视频免费网站 | 亚洲国产高清在线 | 91精品国产综合久久久久久丝袜 | 国产精品久久久久久久久久东京 | 草久网 | 久久久久久久国产 | 国产91在线观看 | 欧美精品91 | 日韩精品免费视频 | 国产成人在线电影 | 欧美激情综合五月色丁香小说 | 日韩在线播放欧美字幕 |