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

歡迎訪問 生活随笔!

生活随笔

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

Android

深入理解Android壁纸

發布時間:2023/12/20 Android 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入理解Android壁纸 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本章主要內容:

  • 討論動態壁紙的實現。

  • 在動態壁紙的基礎上討論靜態壁紙的實現。

  • 討論WMS對壁紙窗口所做的特殊處理。

本章涉及的源代碼文件名及位置:

  • WallpaperManagerService.java

frameworks/base/services/java/com/android/server/WallpaperManagerService.java

  • WallpaperService.java

frameworks/base/core/java/android/service/wallpaper/WallpaperService.java

  • ImageWallpaper.java

frameworks/base/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java

  • WallpaperManager.java

frameworks/base/core/java/android/app/WallpaperManager.java

  • WindowManagerService.java

frameworks/base/services/java/com/android/server/wm/WindowManagerService.java

  • WindowStateAnimator.java

frameworks/base/services/java/com/android/server/wm/WindowStateAnimator.java

  • WindowAnimator.java

frameworks/base/services/java/com/android/server/wm/WindowAnimator.java

8.1 初識Android壁紙

本章將對壁紙的實現原理進行討論。在Android中,壁紙分為靜態與動態兩種。靜態壁紙是一張圖片,而動態壁紙則以動畫為表現形式,或者可以對用戶的操作作出反應。這兩種形式看似差異很大,其實二者的本質是統一的。它們都以一個Service的形式運行在系統后臺,并在一個類型為TYPE_WALLPAPER的窗口上繪制內容。進一步講,靜態壁紙是一種特殊的動態壁紙,它僅在窗口上渲染一張圖片,并且不會對用戶的操作作出反應。因此本章將首先通過動態壁紙的實現討論Android壁紙的實現與管理原理,然后在對靜態壁紙的實現做介紹。

Android壁紙的實現與管理分為三個層次:

  • WallpaperService與Engine。同SystemUI一樣,壁紙運行在一個Android服務之中,這個服務的名字叫做WallpaperService。當用戶選擇了一個壁紙之后,此壁紙所對應的WallpaperService便會啟動并開始進行壁紙的繪制工作,因此繼承并定制WallpaperService是開發者進行壁紙開發的第一步。Engine是WallpaperService中的一個內部類,實現了壁紙窗口的創建以及Surface的維護工作。另外,Engine提供了可供子類重寫的一系列回調,用于通知壁紙開發者關于壁紙的生命周期、Surface狀態的變化以及對用戶的輸入事件進行響應。可以說,Engine類是壁紙實現的核心所在。壁紙開發者需要繼承Engine類,并重寫其提供的回調以完成壁紙的開發。這一層次的內容主要體現了壁紙的實現原理。

  • WallpaperManagerService,這個系統服務用于管理壁紙的運行與切換,并通過WallpaperManager類向外界提供操作壁紙的接口。當通過WallpaperManagaer的接口進行壁紙的切換時,WallpaperManagerService會取消當前壁紙的WallpaperService的綁定,并啟動新壁紙的WallpaperService。另外,Engine類進行窗口創建時所使用的窗口令牌也是由WallpaperManagerService提供的。這一層次主要體現了Android對壁紙的管理方式。

  • WindowManagerService,用于計算壁紙窗口的Z序、可見性以及為壁紙應用窗口動畫。壁紙窗口(TYPE_WALLPAPER)的Z序計算不同于其他類型的窗口。其他窗口依照其類型會有固定的mBaseLayer以及mSubLayer,并結合它們所屬的Activity的順序或創建順序進行Z序的計算,因此這些窗口的Z序相對固定。而壁紙窗口則不然,它的Z序會根據FLAG_SHOW_WALLPAPER標記在其它窗口的LayoutParams.flags中的存在情況而不斷地被調整。這一層次主要體現了Android對壁紙窗口的管理方式。

本章將通過對動態壁紙切換的過程進行分析揭示WallpaperService、Engine以及WallpaperManagerService三者的實現原理以及協作情況。靜態壁紙作為動態壁紙的一種特殊情況,將會在完成動態壁紙的學習之后于8.3節進行討論。而WindowManagerService對壁紙窗口的處理將在8.4節進行介紹。

8.2 深入理解動態壁紙

8.2.1 啟動動態壁紙的方法

啟動動態壁紙可以通過調用WallpaperManager.getIWallpaperManager().setWallpaperComponent()方法完成。它接受一個ComponentName類型的參數,用于將希望啟動的壁紙的WallpaperService的ComponentName告知WallpaperManagerService。WallpaperManager.getIWallpaperManager()方法返回的是WallpaperManagerService的Bp端。因此setWallpaperComponent()方法的實現位于WallpaperManagerService之中。參考其實現:

[WallpaperManagerService.java-->WallpaperManagerService.setWallpaperComponent()] public void setWallpaperComponent(ComponentNamename) {// 設置動態壁紙需要調用者擁有一個簽名級的系統權限checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);synchronized (mLock) {/* **① 首先從mWallpaperMap中獲取壁紙的運行信息WallpaperData。**WallpaperManagerService支持多用戶機制,因此設備上的每一個用戶可以設置自己的壁紙。mWallpaperMap中為每一個用戶保存了一個WallpaperData實例,這個實例中保存了和壁紙運行狀態相關的信息。例如WallpaperService的ComponentName,到WallpaperService的ServiceConnection等。于是當發生用戶切換時,WallpaperManagerService可以從mWallpaperMap中獲取新用戶的WallpaperData,并通過保存在其中的ComponentName重新啟動該用戶所設置的壁紙。因此,當通過setWallpaperComponent()設置新壁紙時,需要獲取當前用戶的WallpaperData,并在隨后更新其內容使之保存新壁紙的信息 */intuserId = UserHandle.getCallingUserId();WallpaperData wallpaper = mWallpaperMap.get(userId);......final long ident = Binder.clearCallingIdentity();try{......// **② 啟動新壁紙的WallpaperService**bindWallpaperComponentLocked(name, false, true, wallpaper, null);}finally {Binder.restoreCallingIdentity(ident);}} }

注意 WallpaperManager.getIWallpaperManager()并沒有作為SDK的一部分提供給開發者。因此第三方應用程序是無法進行動態壁紙的設置的。

8.2.2 壁紙服務的啟動原理

(1)壁紙服務的驗證與啟動

bindWallpaperComponentLocked()方法將會啟動由ComponentName所指定的WallpaperService,并向WMS申請用于添加壁紙窗口的窗口令牌。不過在此之前,bindWallpaperComponentLocked()會對ComponentName所描述的Service進行一系列的驗證,以確保它是一個壁紙服務。而這一系列的驗證過程體現了一個Android服務可以被當作壁紙必要的條件。

[WallpaperManagerService.java-->WallpaperManagerService.setWallpaperComponentLocked()] boolean bindWallpaperComponentLocked(ComponentNamecomponentName, boolean force,boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {......try {/* 當componentName為null時表示使用默認壁紙。這里會將componentName參數改為默認壁紙的componentName */if(componentName == null) {/* 首先會嘗試從com.android.internal.R.string.default_wallpaper_component中獲取默認壁紙的componentName。這個值的設置位于res/values/config.xml中,開發者可以通過修改這個值設置默認壁紙*/String defaultComponent = mContext.getString(com.android.internal.R.string.default_wallpaper_component);if (defaultComponent != null) {componentName = ComponentName.unflattenFromString(defaultComponent);}/* 倘若在上述的資源文件中沒有指定一個默認壁紙,即default_wallpaper_component的值被設置為@null),則使用ImageWallpaper代替默認壁紙。ImageWallpaper就是前文所述的靜態壁紙 */if (componentName == null) {componentName = IMAGE_WALLPAPER;}}/* 接下來WallpaperMangerService會嘗試從PackageManager中嘗試獲取ComponentName所指定的Service的描述信息,獲取此信息的目的在于確認該Service是一個符合要求的壁紙服務 */intserviceUserId = wallpaper.userId;ServiceInfo si = mIPackageManager.getServiceInfo(componentName,PackageManager.GET_META_DATA |PackageManager.GET_PERMISSIONS,serviceUserId);/* **① 第一個檢查,要求這個Service必須聲明其訪問權限為BIND_WALLPAPER。**這個簽名級的系統權限這是為了防止壁紙服務被第三方應用程序啟動而產生混亂 */if(!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {if (fromUser) {throw new SecurityException(msg);}return false;}WallpaperInfo wi = null;/* **② 第二個檢查,要求這個Service必須可以用來處理** **?????????? android.service.wallpaper.WallpaperService這個Action。**其檢查方式是從PackageManager中查詢所有可以處理android.service.wallpaper.WallpaperService的服務,然后檢查即將啟動的服務是否在PackageManager的查詢結果之中 */Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);if(componentName != null && !componentName.equals(IMAGE_WALLPAPER)) {// 獲取所有可以處理android.service.wallpaper.WallpaperService的服務信息List<ResolveInfo> ris =mIPackageManager.queryIntentServices(intent,intent.resolveTypeIfNeeded(mContext.getContentResolver()),PackageManager.GET_META_DATA, serviceUserId);/* **③ 第三個檢查,要求這個Service必須在其meta-data中提供關于壁紙的描述信息。**如果即將啟動的服務位于查詢結果之中,便可以確定這是一個壁紙服務。此時會創建一個WallpaperInfo的實例以解析并存儲此壁紙服務的描述信息。壁紙服務的描述信息包含了壁紙的開發者、縮略圖、簡單的描述文字以及用于對此壁紙進行參數設置的Activity的名字等。壁紙開發者可以在AndroidManifest.xml中將一個包含了上述信息的xml文件設置在名為android.service.wallpaper的meta-data中以提供這些信息 */for (int i=0; i<ris.size(); i++) {ServiceInfo rsi = ris.get(i).serviceInfo;if (rsi.name.equals(si.name) &&rsi.packageName.equals(si.packageName)){try {wi = newWallpaperInfo(mContext, ris.get(i));} catch (XmlPullParserException e) {......}break;}}if (wi == null) {/* wi為null表示即將啟動的服務沒有位于查詢結果之中,或者沒有提供必須的meta-data。此時返回false表示綁定失敗 */return false;}}......}...... }

可見WallpaperManagerService要求被啟動的目標Service必須滿足以下三個條件:

  • 該服務必須要以android.permission.BIND_WALLPAPER作為其訪問權限。壁紙雖然是一個標準的Android服務,但是通過其他途徑(如第三方應用程序)啟動壁紙所在的服務是沒有意義的。因此Android要求作為壁紙的Service必須使用這個簽名級的系統權限進行訪問限制,以免被意外的應用程序啟動。

  • 該服務必須被聲明為可以處理android.service.wallpaper.WallpaperService這個Action。WallpaperManagerService會使用這個Action對此服務進行綁定。

  • 該服務必須在其AndroidManifest.xml中提供一個名為android.service.wallpaper的meta-data,用于提供動態壁紙的開發者、縮略圖與描述文字。

一旦目標服務滿足了上述條件,WallpaperManagerService就會著手進行目標服務的啟動與綁定。

參考setWallpaperComponentLocked()方法的后續代碼:

[WallpaperManagerService.java-->WallpaperManagerService.setWallpaperComponentLocked()] boolean bindWallpaperComponentLocked(ComponentNamecomponentName, boolean force,boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {...... // 檢查服務是否符合要求的代碼/* **① 創建一個WallpaperConnection。**它不僅實現了ServiceConnection接口用于監聽和WallpaperService之間的連接狀態,同時還實現了IWallpaperConnection.Stub,也就是說它支持跨進程通信。在服務綁定成功后的WallpaperConnection.onServiceConnected()方法調用中,WallpaperConnection的實例會被發送給WallpaperService,使其作為WallpaperService向WallpaperManagerService進行通信的橋梁 */WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper);// 為啟動壁紙服務準備Intentintent.setComponent(componentName);intent.putExtra(Intent.EXTRA_CLIENT_LABEL,com.android.internal.R.string.wallpaper_binding_label);intent.putExtra(Intent.EXTRA_CLIENT_INTENT,PendingIntent.getActivityAsUser(mContext, 0,Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),mContext.getText(com.android.internal.R.string.chooser_wallpaper)),0, null, new UserHandle(serviceUserId)));/* **② 啟動制定的壁紙服務。**當服務啟動完成后,剩下的啟動流程會在WallpaperConnection.onServiceConnected()中繼續 */if(!mContext.bindService(intent,newConn,Context.BIND_AUTO_CREATE, serviceUserId)) {}// **③ 新的的壁紙服務啟動成功后,便通過detachWallpaperLocked()銷毀舊有的壁紙服務**if(wallpaper.userId == mCurrentUserId && mLastWallpaper != null) {detachWallpaperLocked(mLastWallpaper);}// **④ 將新的壁紙服務的運行信息保存到WallpaperData中**wallpaper.wallpaperComponent = componentName;wallpaper.connection = newConn;/* 設置wallpaper.lastDiedTime。這個成員變量與其說描述壁紙的死亡時間戳,不如說是描述其啟動的時間戳。它用來在壁紙服務意外斷開時(即壁紙服務非正常停止)檢查此壁紙服務的存活時間。當存活時間小于一個特定的時長時將會認為這個壁紙的軟件質量不可靠從而選擇使用默認壁紙,而不是重啟這個壁紙服務 */wallpaper.lastDiedTime = SystemClock.uptimeMillis();newConn.mReply = reply;/* **④ 最后向WMS申請注冊一個WALLPAPER類型的窗口令牌。**這個令牌會在onServiceConnected()之后被傳遞給WallpaperService用于作為后者添加窗口的通行證 */try{if (wallpaper.userId == mCurrentUserId) {mIWindowManager.addWindowToken(newConn.mToken,WindowManager.LayoutParams.TYPE_WALLPAPER);mLastWallpaper = wallpaper;}} catch (RemoteException e) {}} catch(RemoteException e) {}returntrue; }

bindWallpaperComponentLocked()主要做了如下幾件事情:

  • 創建WallpaperConnection。由于實現了ServiceConnection接口,因此它將負責監聽WallpaperManagerService與壁紙服務之間的連接狀態。另外由于繼承了IWallpaperConnection.Stub,因此它具有跨進程通信的能力。在壁紙服務綁定成功后,WallpaperConnection實例會被傳遞給壁紙服務作為壁紙服務與WallpaperManagerService進行通信的橋梁。

  • 啟動壁紙服務。通過Context.bindService()方法完成。可見啟動壁紙服務與啟動一個普通的服務沒有什么區別。

  • 終止舊有的壁紙服務。

  • 將屬于當前壁紙的WallpaperConnection實例、componentName機器啟動時間戳保存到WallpaperData中。

  • 向WMS注冊WALLPAPER類型的窗口令牌。這個窗口令牌保存在WallpaperConnection.mToken中,并隨著WallpaperConnection的創建而創建。

僅僅將指定的壁紙服務啟動起來尚無法使得壁紙得以顯示,因為新啟動起來的壁紙服務由于沒有可用的窗口令牌而導致其無法添加窗口。WallpaperManagerService必須通過某種方法將窗口令牌交給壁紙服務才行。所以壁紙顯示的后半部分的流程將在WallpaperConnection.onServiceConnected()回調中繼續。同其他服務一樣,WallpaperManagerService會在這個回調之中獲得一個Binder對象。因此在進行onServiceConnected()方法的討論之前,必須了解WallpaperManagerService在這個回調中將會得到一個什么樣的Binder對象。

現在把分析目標轉移到WallpaperService中。和普通服務一樣,WallpaperService的啟動也會經歷onCreate()、onBind()這樣的生命周期回調。為了了解WallpaperManagerService可以從onServiceConnected()獲取怎樣的Binder對象,需要看下WallpaperService.onBind()的實現:

[WallpaperService.java-->WallpaperService.onBind()] public final IBinder onBind(Intent intent) {/*onBind()新建了一個IWallpaperServiceWrapper實例,并將其返回給WallpaperManagerService */returnnew IWallpaperServiceWrapper(this); }

IWallpaperServiceWrapper類繼承自IWallpaperService.Stub。它保存了WallpaperService的實例,同時也實現了唯一的一個接口attach()。很顯然,當這個Binder對象返回給WallpaperManagerService之后,后者定會調用這個唯一的接口attach()以傳遞顯示壁紙所必須的包括窗口令牌在內的一系列的參數。

(2)向壁紙服務傳遞創建窗口所需的信息

重新回到WallpaperManagerService,當WallpaperService創建了IWallpaperServiceWrapper實例并返回后,WallpaperManagerService將會在WallpaperConnection.onServiceConnected()中收到回調。參考其實現:

[WallpaperManagerService.java-->WallpaperConnection.onServiceConnected()] public void onServiceConnected(ComponentName name,IBinder service) {synchronized (mLock) {if (mWallpaper.connection == this) {// 更新壁紙的啟動時間戳mWallpaper.lastDiedTime = SystemClock.uptimeMillis();// **① 將WallpaperService傳回的IWallpaperService接口保存為mService**mService = IWallpaperService.Stub.asInterface(service);/* **② 綁定壁紙服務。**attachServiceLocked()會調用IWallpaperService.attach()方法以將壁紙服務創建窗口所需的信息傳遞過去 */attachServiceLocked(this, mWallpaper);// **③ 保存當前壁紙的運行狀態到文件系統中,以便在系統重啟或發生用戶切換時可以恢復**saveSettingsLocked(mWallpaper);}} } 進一步地,attachServiceLocked()方法會調用IWallpaperService.attach()方法,將創建壁紙窗口所需的信息發送給壁紙服務。 [WallpaperManagerService.java-->WallpaperManagerService.attachServiceCLocked()] void attachServiceLocked(WallpaperConnection conn,WallpaperData wallpaper) {try {/* 調用IWallpaperService的唯一接口attach(),將創建壁紙窗口所需要的參數傳遞給WallpaperService */conn.mService.attach(conn, conn.mToken,WindowManager.LayoutParams.TYPE_WALLPAPER, false,wallpaper.width, wallpaper.height);} catch(RemoteException e) {......} }

attach()方法的參數很多,它們的意義如下:

  • conn即WallpaperConnection,WallpaperService將通過它向WallpaperManagerService進行通信。WallpaperConnection繼承自IWallpaperConnection,只提供了兩個接口的定義,即attachEngine()以及engineShown()。雖說WallpaperManager是WallpaperManagerService向外界提供的標準接口,但是這里仍然選擇使用WallpaperConnection實現這兩個接口的原因是由于attachEngine()以及engineShown()是只有WallpaperService才需要用到而且是它與 WallpaperManagerService之間比較底層且私密的交流,將它們的實現放在通用的接口WallpaperManager中顯然并不合適。這兩個接口中比較重要的當屬attachEngine()了。如前文所述,Engine類是實現壁紙的核心所在,而WallpaperService只是一個用于承載壁紙的運行的容器而已。因此相對于WallpaperService,Engine是WallpaperManagerService更加關心的對象。所以當WallpaperService完成了Engine對象的創建之后,就會通過attachEngine()方法將Engine對象的引用交給WallpaperManagerService。

  • conn.mToken就是在bindWallpaperComponent()方法中向WMS注冊過的窗口令牌。是WallpaperService有權添加壁紙窗口的憑證。

  • WindowManager.LayoutParams.TYPE_WALLPAPER指明了WallpaperService需要添加TYPE_WALLPAPER類型的窗口。讀者可能會質疑這個參數的意義:壁紙除了是TYPE_WALLPAPER類型以外難道還有其他的可能么?的確在實際的壁紙顯示中WallpaperService必然需要使用TYPE_WALLPAPER類型添加窗口。但是有一個例外,即壁紙預覽。在LivePicker應用中選擇一個動態壁紙時,首先會使得用戶對選定的壁紙進行預覽。這一預覽并不是真的將壁紙設置給了WallpaperManagerService,而是LivePicker應用自行啟動了對應的壁紙服務,并要求壁紙服務使用TYPE_APPLICATION_MEDIA_OVERLAY類型創建窗口。這樣一來,壁紙服務所創建的窗口將會以子窗口的形式襯在LivePicker的窗口之下,從而實現了動態壁紙的預覽。

  • false的參數名是isPreview. 用以指示啟動壁紙服務的意圖。當被實際用作壁紙時取值為false,而作為預覽時則為true。僅當LivePicker對壁紙進行預覽時才會使用true作為isPreview的取值。壁紙服務可以根據這一參數的取值對自己的行為作出調整。

當WallpaperManagerService向WallpaperService提供了用于創建壁紙窗口的足夠的信息之后,WallpaperService便可以開始著手進行Engine對象的創建了。

(3)Engine的創建

調用IWallpaperService.attach()是WallpaperManagerService在壁紙服務啟動后第一次與壁紙服務進行聯系。參考其實現:

[WallpaperService.java-->IWallpaperServiceWrapper.attach()] public void attach(IWallpaperConnection conn,IBinder windowToken,intwindowType, boolean isPreview, int reqWidth, int reqHeight) {// 使用WallpaperManagerService提供的參數構造一個IWallpaperEngineWarapper實例newIWallpaperEngineWrapper(mTarget, conn, windowToken,windowType, isPreview, reqWidth, reqHeight); }

顧名思義,在attach()方法中所創建的IWallpaperEngineWrapper將會創建并封裝Engine實例。IWallpaperEngineWrapper繼承自IWallpaperEngine.Stub,因此它也支持跨Binder調用。在隨后的代碼分析中可知,它將會被傳遞給WallpaperManagerService,作為WallpaperManagerService與Engine進行通信的橋梁。

另外需要注意的是,attach()方法的實現非常奇怪,它直接創建一個實例但是并沒有將這個實例賦值給某一個成員變量,在attach()方法結束時豈不是會被垃圾回收?不難想到,在IWallpaperEngineWrapper的構造函數中一定有些動作可以使得這個實例不被釋放。參考其實現:

[WallpaperService.java-->IWallpaperEngineWrapper.IWallpaperEngineWrapper()] IWallpaperEngineWrapper(WallpaperService context,IWallpaperConnection conn, IBinder windowToken,intwindowType, boolean isPreview, int reqWidth, int reqHeight) {/* 創建一個HandlerCaller。HandlerCaller是Handler的一個封裝,而它與Handler的區別是額外提供了一個executeOrSendMessage()方法。當開發者在HandlerCaller所在的線程執行此方法時會使得消息的處理函數立刻得到執行,在其他線程中執行此方法的效果則與Handler.sendMessage()別無二致。除非閱讀代碼時遇到這個方法,讀者只需要將其理解為Handler即可。注意意通過其構造函數的參數可知HandlerCaller保存了IWallpaperEngineWrapper的實例 */mCaller= new HandlerCaller(context,mCallbackLooper != null? mCallbackLooper : context.getMainLooper(),this);// 將WallpaperManagerService所提供的參數保存下來mConnection = conn; // conn即是WallpaperManagerService中的WallpaperConnectionmWindowToken = windowToken;mWindowType = windowType;mIsPreview = isPreview;mReqWidth = reqWidth;mReqHeight = reqHeight;// 發送DO_ATTACH消息。后續的流程轉到DO_ATTACH消息的處理中進行Messagemsg = mCaller.obtainMessage(DO_ATTACH);mCaller.sendMessage(msg); }

注意 在這里貌似并沒有保存新建的IWallpaperEngineWrapper實例,它豈不是有可能在DO_ATTACH消息執行前就被Java的垃圾回收機制回收了?其實不是這樣。HandlerCaller的構造函數以及最后的sendMessage()操作使得這個IWallpaperEngineWrapper的實例得以堅持到DO_ATTACH消息可以得到處理的時刻。sendMessage()方法的調用使得Message被目標線程的MessageQueue引用,并且對應的Handler的被Message引用,而這個Handler是HandlerCaller的內部類,因此在Handler中有一個隱式的指向HandlerCaller的引用,最后在HandlerCaller中又存在著IWallpaperEngineWrapper的引用。因此IWallpaperEngineWrapper間接地被HandlerCaller所在線程的MessageQueue所引用著,因此在完成DO_ATTACH消息的處理之前,IWallpaperEngineWrapper并不會被回收。雖然這是建立在對Java引用以及Handler工作原理的深刻理解之上所完成的精妙實現,但是它確實已經接近危險的邊緣了。

在這里所創建的mCaller具有十分重要的地位。它是一個重要的線程調度器,所有壁紙相關的操作都會以消息的形式發送給mCaller,然后在IWallpaperEngineWrapper的executeMessage()方法中得到處理,從而這些操作轉移到mCaller所在的線程上進行(如壁紙繪制、事件處理等)。可以說mCaller的線程就是壁紙的工作線程。默認情況下這個mCaller運行在壁紙服務的主線程上即context.getMainLooper()。不過當WallpaperService.mCallbackLooper不為null時會運行在mCallbackLooper所在的線程。mCaller運行在壁紙服務的主線程上聽起來十分合理,然而提供手段以允許其運行在其他線程的做法卻有些意外。其實這是為了滿足一種特殊的需求,以ImageWallper壁紙服務為例,它是SystemUI的一部分而SystemUI的主線程主要用來作為狀態欄、導航欄的管理與繪制的場所,換句話說其主線程的工作已經比較繁重了。因此ImageWallpaper可以通過這一手段將壁紙的工作轉移到另外一個線程中進行。不過因為這一機制可能帶來同步上的問題,因此在Android 4.4及后續版本中被廢除了。

接下來分析DO_ATTACH消息的處理:

[WallpaperService.java-->IWallpaperEngineWrapper.executeMessage()] public void executeMessage(Message message) {switch(message.what) {caseDO_ATTACH: {try {/* **① 把IWallpaperEngineWrapper實例傳遞給WallpaperConnection進行保存。**至此這個實例便名花有主,再也不用擔心被回收了,而且WallpaperManagerService還可以通過它與實際的Engine進行通信 */mConnection.attachEngine(this);} catch (RemoteException e) {}/* **② 通過onCreateEngine()方法創建一個Engine。**onCreateEngine()是定義在WallpaperService中的一個抽象方法。WallpaperService的實現者需要根據自己的需要返回一個自定義的Engine的子類 */Engine engine = onCreateEngine();mEngine = engine;/* **③ 將新建的Engine添加到WallpaperService.mActiveEngines列表中。**讀者可能會比較奇怪,為什么是列表?難道一個Wallpaper可能會有多個Engine么?這個奇怪之處還是壁紙預覽所引入的。當壁紙A已經被設置為當前壁紙之時,系統中會存在一個它所對應的WallpaperService,以及在其內部會存在一個Engine。此時當LivePicker或其他壁紙管理工具預覽壁紙A時,它所對應的WallpaperService仍然只有一個,但是在其內部會變成兩個Engine。這一現象更能說明,WallpaperService僅僅是提供壁紙運行的場所,而Engine才是真正的壁紙的實現 */mActiveEngines.add(engine);// **④ 最后engine.attach()將會完成窗口的創建、第一幀的繪制等工作**engine.attach(this);return;}} }

正如前文所述,作為擁有跨Binder調用的IWallpaperEngineWrapper通過attachEngine()方法將自己傳遞給了WallpaperConnection,后者將其保存在WallpaperConnection.mEngine成員之中。從此之后,WallpaperManagerService便可以通過WallpaperConnection.mEngine與壁紙服務進程中的IWallpaperEngineWrapper進行通信,而IWallpaperEngineWrapper進一步將來自WallpaperManagerService中的請求或設置轉發給Engine對象,從而實現了WallpaperManagerService對壁紙的控制。

到目前為止,WallpaperManagerService與壁紙服務之間已經出現了三個用于跨Binder通信的對象。它們分別是:

  • IWallpaperService,實現在壁紙服務進程之中,它所提供的唯一的方法attach()用于在壁紙服務啟動后接收窗口創建所需的信息,或者說為了完成壁紙的初始化工作。除此之外IWallpaperService不負責任何功能,WallpaperManagerService對壁紙進行的請求與設置都交由在attach()的過程中所創建的IWallpaperEngineWrapper實例完成。

  • WallpaperConnection,實現在WallpaperManagerService中,并通過IWallpaperService.attach()方法傳遞給了IWallpaperEngineWrapper。壁紙服務通過WallpaperConnection的attachEngine()方法將IWallpaperEngineWrapper實例傳遞給WallpaperManagerService進行保存。另外壁紙服務還通過它的engineShown()方法將壁紙顯示完成的事件通知給WallpaperManagerService。

  • IWallpaperEngineWrapper,實現在壁紙進程中。Engine實例是壁紙實現的核心所在。作為Engine實例的封裝者,它是WallpaperManagerService對Engine進行請求或設置的唯一接口。

總體來說,IWallpaperService與WallpaperConnection主要服務于壁紙的創建階段,而IWallpaperEngineWrapper則用于在壁紙的運行階段對Engine進行操作與設置。

說明 按照常規的思想來推斷,WallpaperManagerService與WallpaperService之間應該僅僅需要IWallpaperService提供接口對壁紙進行操作與設置。為什么要增加一個IWallpaperEngineWrapper呢?這得從WallpaperService與Engine之間的關系說起。IWallpaperService在WallpaperManagerService看來表示的是WallpaperService,而IWallpaperEngineWrapper則表示的是Engine。WallpaperService是Engine運行的容器,因此它所提供的唯一的方法attach()用來在WallpaperService中創建新的Engine實例(由創建一個IWallpaperEngineWrapper實例來完成)。Engine則是壁紙的具體實現,因此IWallpaperEngineWrapper所提供的方法用來對壁紙進行操作與設置。從這個意義上來講IWallpaperService與IWallpaperEngineWrapper的同時存在是合理的。另外,將IWallpaperService與IWallpaperEngineWrapper分開還有著簡化實現的意義。從DO_ATTACH消息的處理過程可知,WallpaperService中可以同時運行多個Engine實例。而WallpaperManagerService或LivePicker所關心的只是某一個Engine,而不是WallpaperService中的所有Engine,因此相對于使用IWallpaperService的接口時必須在參數中指明所需要操作的Engine,直接操作IWallpaperEngineWrapper更加簡潔直接。

Engine創建完畢之后會通過Engine.attach()方法完成Engine的初始化工作。參考其代碼:

[WallpaperService.java-->Engine.attach()] void attach(IWallpaperEngineWrapper wrapper) {......// 保存必要的信息mIWallpaperEngine = wrapper;mCaller= wrapper.mCaller;mConnection = wrapper.mConnection;mWindowToken = wrapper.mWindowToken;/* **① mSurfaceHolder是一個BaseSurfaceHolder類型的內部類的實例。**Engine對其進行了簡單的定制。開發者可以通過mSurfaceHolder定制所需要的Surface類型 */mSurfaceHolder.setSizeFromLayout();mInitializing = true;// 獲取WindowSession,用于與WMS進行通信mSession= WindowManagerGlobal.getWindowSession(getMainLooper());//mWindow是IWindow的實現,窗口創建之后它將用于接收來自WMS的回調mWindow.setSession(mSession);//Engine需要監聽屏幕狀態。這是為了保證在屏幕關閉之后,動態壁紙可以停止動畫的渲染以節省電量mScreenOn =((PowerManager)getSystemService(Context.POWER_SERVICE)).isScreenOn();IntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_SCREEN_ON);filter.addAction(Intent.ACTION_SCREEN_OFF);registerReceiver(mReceiver, filter);/* **② 調用Engine.onCreate()。**Engine的子類往往需要重寫此方法以修改mSurfaceHolder的屬性,如像素格式,尺寸等。注意此時尚未創建窗口,在這里所設置的SurfaceHolder的屬性將會在創建窗口時生效 */onCreate(mSurfaceHolder);mInitializing = false;mReportedVisible = false;/* **③ 最后updateSurface將會根據SurfaceHolder的屬性創建窗口以及Surface,并進行** **????? 壁紙的第一次繪制** */updateSurface(false, false, false); }

Engine.attach()方法執行的結束標志著壁紙啟動工作的完成,至此在最后的updateSurface()方法結束之后新的壁紙便顯示出來了。

(4)壁紙的創建流程

可見,壁紙的創建過程比較復雜。在這個過程中存在著多個Binder對象之間的互相調用。因此有必要對此過程進行一個簡單的整理:

  • 首先,壁紙管理程序(如LivePicker)調用IWallpaperManager.setWallpaperComponent()要求WallpaperManagerService設置指定的壁紙

  • WallpaperManagerService通過調用bindWallpaperComponentLocked()將給定的壁紙服務啟動起來。同時舊有的壁紙服務會被終止。

  • WallpaperManagerService成功連接壁紙服務后,調用壁紙服務的attach()方法將窗口令牌等參數交給壁紙服務。

  • 壁紙服務響應attach()的調用,創建一個Engine。

  • Engine的updateSurface()方法將會創建壁紙窗口及Surface,并進行壁紙的繪制。

而在這個過程中,WallpaperManagerService中存在如下重要的數據結構:

  • WallpaperInfo,存儲了動態壁紙的開發者、縮略圖與描述信息。這個數據結構創建于WallpaperManagerService.bindWallpaperComponentLocked()方法,其內容來自于壁紙所在應用程序的AndroidManifest.xml中名為android.service.wallpaper的meta-data。

  • WallpaperConnection,它不僅僅是壁紙服務與WallpaperManagerService進行通信的渠道,它同時也保存了與壁紙服務相關的重要的運行時信息,如IWallpaperService、IWallpaperEngineWrapper、WallpaperInfo以及用于創建窗口所需的窗口令牌。WallpaperConnection創建于WallpaperManagerService.bindWallpaperComponentLocked()方法。

  • WallpaperData,它保存了一個壁紙在WallpaperManagerService中可能用到的所有信息,包括壁紙服務的ComponentName,WallpaperConnection,壁紙服務的啟動時間等。WallpaperData被保存在一個名為mWallpaperMap的SparseArray中,而且設備中每一個用戶都會擁有一個固定的WallpaperData實例。當前用戶進行壁紙切換時會更新WallpaperData的內容,而不是新建一個WallpaperData實例。另外,WallpaperData中還保存了與靜態壁紙相關的一些信息,關于靜態壁紙的內容將在8.3節進行介紹。

壁紙的創建過程同時體現了壁紙服務與WallpaperManagerService之間的關系,如圖8-1所示。

圖 8 - 1 壁紙服務與WallpaperManagerService之間的關系

總結

以上是生活随笔為你收集整理的深入理解Android壁纸的全部內容,希望文章能夠幫你解決所遇到的問題。

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

婷婷丁香七月 | av黄色在线| www.国产在线观看 | 日韩av专区 | 亚洲六月丁香色婷婷综合久久 | 欧美成亚洲 | 97超碰超碰久久福利超碰 | 国产精品亚洲片夜色在线 | 日本福利视频在线 | 91精品一区国产高清在线gif | 精品国产激情 | 日日夜夜精品免费 | 天天av资源 | 探花视频在线观看+在线播放 | 黄a在线观看 | 亚洲精品五月天 | 免费精品国产 | 成人免费视频网址 | 久草在线最新免费 | 亚洲精品乱码久久久久久高潮 | 国产精品国产三级在线专区 | 黄网站app在线观看免费视频 | 狠狠久久伊人 | 日韩av成人 | 欧美日韩三级在线观看 | 久久天天躁狠狠躁亚洲综合公司 | 97超碰中文字幕 | 成人福利av| 日本精品视频在线 | 日韩av有码在线 | 国产精品一区二区吃奶在线观看 | 久久久久久国产精品亚洲78 | 麻豆视频免费在线观看 | 亚洲精品久久久蜜臀下载官网 | 色婷婷九月 | 在线不卡视频 | 青青久草在线视频 | 最新精品国产 | 久久艹中文字幕 | 国产精品久久久久久久久费观看 | 五月婷婷亚洲 | 中文字幕视频三区 | 91九色在线视频观看 | 日韩高清www | 亚洲有 在线 | 国产色在线观看 | 久久 亚洲视频 | 国内久久久久 | 国产精品久久久久久妇 | 中文在线8新资源库 | 不卡精品 | 色成人亚洲网 | 91免费看片黄 | 午夜精品麻豆 | 亚洲国产剧情 | 国产日韩欧美精品在线观看 | 日日夜夜精品免费观看 | 超碰97在线人人 | 免费美女av | 久草在线费播放视频 | 在线精品在线 | 国产精品国产三级国产aⅴ入口 | 日本精品va在线观看 | 亚洲一级免费电影 | 亚洲视频,欧洲视频 | 成人动漫精品一区二区 | 久久久免费精品国产一区二区 | av电影在线不卡 | 国产韩国精品一区二区三区 | 国产精品久久久久久久久久久不卡 | 一区二区三区四区在线免费观看 | 国产精品成人免费一区久久羞羞 | 亚洲人成人天堂h久久 | av一级久久 | 最近免费观看的电影完整版 | 亚洲欧美国产精品久久久久 | www.天天干 | 国产精品一区二区三区在线 | av看片在线 | 九九视频免费 | av在线电影免费观看 | 婷婷色 亚洲 | 国产精品成人免费一区久久羞羞 | 91看片一区二区三区 | 五月天丁香综合 | 精品乱码一区二区三四区 | 中文字幕日本电影 | 日本黄网站 | 亚洲日本一区二区在线 | avcom在线 | 免费看三级黄色片 | 国产一区高清在线 | 四虎在线永久免费观看 | 国产爽妇网 | 亚洲精品午夜aaa久久久 | 亚洲激情婷婷 | 中国一级片在线播放 | 狠狠操夜夜操 | 国产精品白丝av | av资源免费在线观看 | 精品久久久久久久久中文字幕 | 天天天干天天天操 | 91中文在线视频 | 激情久久五月天 | 欧美最爽乱淫视频播放 | 天天操狠狠干 | 国产色秀视频 | 亚洲男男gaygay无套同网址 | 日韩啪啪小视频 | 国产专区精品视频 | 亚洲一区二区三区四区在线视频 | 亚洲九九九在线观看 | 男女男视频 | 色综合天天视频在线观看 | 五月综合在线观看 | 久久精品人人做人人综合老师 | 久久国产精品精品国产色婷婷 | 黄色亚洲 | 中文在线www | 日日日视频 | 69av久久 | 日韩视频免费在线 | www.97色.com| 久久精品在线 | 在线观看黄网站 | 日本黄色免费看 | 国产中文字幕91 | 色综合婷婷 | 国产精品 日韩 欧美 | 91成人在线观看喷潮 | 精品在线视频播放 | 精品在线二区 | 激情综合色播五月 | 日韩欧美xxxx| av电影免费看 | 欧美色就是色 | 国产国语在线 | 天天综合久久 | 在线成人观看 | 99精品在线播放 | 国产一区二区在线看 | 色婷婷福利 | a√天堂资源 | 黄色三级av | 国产精品婷婷午夜在线观看 | 国产精品久久久久久久久久久不卡 | 久产久精国产品 | 国产免费不卡 | 国产一区二区中文字幕 | 天天干 夜夜操 | 日日日干| 亚洲欧美999| 69亚洲视频| 色悠悠久久综合 | 最新国产精品拍自在线播放 | 欧美福利片在线观看 | 精品国产激情 | 国产美女免费 | 国内精品久久久久久久97牛牛 | 中文字幕免费不卡视频 | 欧美一区二区三区激情视频 | 综合中文字幕 | 黄免费网站 | 97超碰资源站 | 六月天色婷婷 | 超碰97网站 | 欧美a级片免费看 | 国产精品自产拍在线观看 | 久久免费毛片视频 | 国产精品国产三级在线专区 | 久久久久福利视频 | 免费进去里的视频 | 久久综合给合久久狠狠色 | 欧美日韩午夜在线 | 国产亚洲人成网站在线观看 | 97韩国电影 | 西西4444www大胆无视频 | 日本三级在线观看中文字 | 国内成人av | 黄色软件在线观看免费 | 91探花国产综合在线精品 | 在线国产中文字幕 | 亚洲精品高清在线 | 9ⅰ精品久久久久久久久中文字幕 | 亚洲国产高清在线观看视频 | 欧美一区二区伦理片 | 99久久精品免费 | 一区二区三区精品久久久 | 欧洲性视频| 久av电影| 久久国产精品色av免费看 | 一区二区丝袜 | 中文一区二区三区在线观看 | 99精品国产免费久久久久久下载 | 999成人网| 国产又黄又爽无遮挡 | 成人h电影 | www.午夜视频 | 免费观看十分钟 | 久久综合九色综合欧美就去吻 | 在线日韩一区 | 亚洲电影第一页av | 国产麻豆视频 | 日本久久精| 久久综合国产伦精品免费 | 国产精品a级 | 国产精成人品免费观看 | www.夜夜骑.com| 亚洲六月丁香色婷婷综合久久 | 久久综合操 | 久久久国产视频 | www五月婷婷| 成年免费在线视频 | 天天色婷婷 | 高清不卡一区二区三区 | 亚洲成av人影片在线观看 | 欧美一区二区免费在线观看 | 毛片二区 | 在线播放你懂 | 日韩欧美在线播放 | 久久这里精品视频 | 开心综合网 | www.成人精品 | 免费精品人在线二线三线 | 四虎欧美 | 一区二区三区中文字幕在线 | 国产成人一二三 | 2024国产精品视频 | 久久高视频 | 97av.com| 日韩69av | 国产亚洲精品久久久久久网站 | 成人观看| 91看成人| 99久久9 | 色网站免费在线看 | 国产精品久久久久久久久久妇女 | 91视频免费网址 | 亚洲综合网站在线观看 | 九九精品毛片 | 热久久最新地址 | 丝袜护士aⅴ在线白丝护士 天天综合精品 | 黄色91在线观看 | 久久国产精品免费观看 | 337p日本欧洲亚洲大胆裸体艺术 | 国产精品久久久免费看 | 狠狠操夜夜 | 久久香蕉一区 | 97手机电影网 | 狠狠的干 | 国产在线不卡精品 | 国产精品九九九九九九 | 亚洲专区一二三 | 免费观看一级成人毛片 | 国产精品久久久久久av | 亚洲视频在线免费看 | 国产精品免费在线播放 | 亚洲精品网址在线观看 | 成人性生交大片免费观看网站 | 中文字幕一区二区三区四区在线视频 | 国产高清视频免费最新在线 | 午夜美女福利直播 | 日韩av在线免费播放 | 欧美精品生活片 | 999电影免费在线观看2020 | 精品国产诱惑 | 综合网在线视频 | 欧美激情视频一二三区 | 一区二区三区免费在线观看视频 | 久久久久久久久久久影视 | 国产精品毛片一区二区三区 | 欧美一级免费高清 | 午夜电影av| 在线视频 你懂得 | 久久五月婷婷丁香 | 最近中文字幕视频网 | 国产日韩欧美在线观看视频 | 91成人国产| 69视频在线播放 | 精品人人人 | 九色91av| 日韩在线不卡视频 | 久久久麻豆精品一区二区 | 麻豆免费在线播放 | 免费观看xxxx9999片 | 精品久久免费看 | 天天插日日操 | 精品国产一区二区三区久久久蜜月 | 免费a视频 | 97中文字幕 | 日韩免费一二三区 | 人人爽人人| 91亚洲精品久久久蜜桃借种 | 超碰人人干人人 | 99爱视频在线观看 | 日本公妇色中文字幕 | 国产精品免费在线视频 | 激情久久久久 | 日本中出在线观看 | 成人香蕉视频 | 久久久激情视频 | 日韩中文在线观看 | 香蕉免费| 免费看十八岁美女 | 亚洲黄色成人 | 久久有精品 | 精品你懂的 | 久久九九久久 | 91成年视频 | 国产高清 不卡 | 日本公妇在线观看高清 | 日韩欧美精品免费 | 午夜国产福利在线观看 | 亚洲jizzjizz日本少妇 | 国产一卡在线 | 中文字幕av在线 | 国产成人精品一二三区 | 国产精品久久久久一区 | 色狠狠综合天天综合综合 | 久久全国免费视频 | 久久久久久久av | av中文字幕在线免费观看 | 欧美精品久久99 | 久艹视频在线免费观看 | 免费久久久久久 | 国产五月天婷婷 | 日韩av一区在线观看 | 国产高清精品在线观看 | av在线免费观看黄 | 500部大龄熟乱视频使用方法 | 日韩av一卡二卡三卡 | 国产不卡精品 | 9色在线视频 | 久久精品超碰 | 亚洲精品日韩av | 欧美日韩在线观看一区二区 | 精品国偷自产在线 | 日韩字幕 | 久久久久久电影 | 欧美另类激情 | 亚洲色五月 | 99精品视频在线观看视频 | 99免费看片 | 国产亚洲精品久久久久5区 成人h电影在线观看 | 黄网站免费大全入口 | 黄色福利网站 | 欧美综合久久久 | 91中文字幕在线观看 | 日韩久久久久久久久 | 国产在线不卡精品 | 欧美日韩国产精品一区 | 人人狠狠综合久久亚洲 | 日韩手机在线观看 | 免费精品视频在线观看 | 天天摸日日操 | 国产精品18久久久久白浆 | 免费毛片aaaaaa | 精品国产乱码久久久久久天美 | 午夜av网站 | 嫩小bbbb摸bbb摸bbb | 一区二区三区精品久久久 | av天天干 | 人人澡人人澡人人 | 人成免费网站 | 亚洲国产欧美在线看片xxoo | 激情视频综合网 | 黄色av免费电影 | 国产xxxx性hd极品 | 色婷婷视频在线 | 狠狠操天天操 | 一区在线免费观看 | 久久99精品视频 | 99久久精品国产亚洲 | 久久久精品一区二区 | 国产色婷婷 | 天天操天天干天天操天天干 | 人人草在线观看 | 一区二区三区中文字幕在线 | 天天操天天操天天操天天操 | 97在线观视频免费观看 | 日韩毛片在线播放 | 国产理论影院 | 欧美激情视频一二区 | 国产一级免费片 | 天天操狠狠操夜夜操 | 久久99精品国产一区二区三区 | 欧美a级一区二区 | 久久优 | 亚洲成人午夜av | 人人干干人人 | 亚洲精品电影在线 | 亚洲天堂网站视频 | 欧美一区二区精美视频 | 亚洲一级片免费观看 | 国产精品18久久久久久不卡孕妇 | 亚洲精品456在线播放第一页 | 成人动态视频 | 久在线观看 | 超碰在线94 | 五月婷婷久久综合 | 国产综合香蕉五月婷在线 | 亚洲伊人av | 国产精品一区二区三区四 | 一区二区三区四区免费视频 | 97日日碰人人模人人澡分享吧 | www.夜夜操.com | 日本性视频 | 看毛片的网址 | 亚洲视频电影在线 | 三级黄色欧美 | 久久免费电影网 | 精品国产美女 | 成年人免费在线 | 天天操偷偷干 | 久久精品电影 | 夜色.com | 亚洲午夜久久久综合37日本 | 久久久久久毛片精品免费不卡 | av在线免费不卡 | 右手影院亚洲欧美 | 99久久婷婷国产一区二区三区 | 国产成人精品一区二区三区福利 | 国产最新精品视频 | 中文资源在线观看 | 午夜天使| 色综合夜色一区 | 婷婷视频 | 五月天婷亚洲天综合网鲁鲁鲁 | 久久亚洲影视 | 欧美一区在线看 | 黄色中文字幕 | 在线网站黄 | 亚洲国产日韩一区 | 亚洲最大的av网站 | 欧美午夜激情网 | 精品久久久久久亚洲综合网 | 久久99精品国产99久久 | 亚洲一级二级 | 国产精品麻 | 亚洲成av人影片在线观看 | 国产一区免费视频 | 三上悠亚在线免费 | 久久不卡av | 久久9视频 | 亚洲黄色精品 | 国产美女免费看 | 在线观看韩日电影免费 | 最近最新中文字幕视频 | 亚洲情感电影大片 | 亚洲一一在线 | 日本精品久久久久中文字幕5 | 特级毛片网站 | 欧美日韩在线视频观看 | 麻豆国产露脸在线观看 | 国产精品久久久久久久av电影 | 九九免费观看全部免费视频 | 久久香蕉影视 | 国产亚洲精品福利 | 国产精品第三页 | 97久久精品午夜一区二区 | 国产精品亚州 | 国产伦精品一区二区三区免费 | 国产精品嫩草在线 | 国产一级久久久 | 99精品视频精品精品视频 | 国精产品999国精产 久久久久 | a电影免费看| 免费精品国产 | 成人国产精品一区 | 久草综合视频 | 日批视频在线播放 | 成人免费色 | 黄色av一区二区三区 | 激情网婷婷 | 中文在线字幕免费观 | 精品视频在线看 | 人人爽人人爽人人爽人人爽 | 久久久一本精品99久久精品 | 精品欧美小视频在线观看 | 国产又粗又猛又黄又爽视频 | 亚洲国产精品久久 | 日本最新一区二区三区 | 亚洲最新av| 91免费看黄 | 狠狠做六月爱婷婷综合aⅴ 日本高清免费中文字幕 | 欧美亚洲成人免费 | 四虎海外影库www4hu | 国产一级性生活 | 久久精品老司机 | 国产视频综合在线 | 国产精品高清在线 | 婷婷精品在线视频 | 免费不卡中文字幕视频 | www.夜夜| 国产资源在线视频 | 97视频免费在线观看 | 97精品电影院 | 久久久久久免费网 | 色偷偷中文字幕 | 日韩中文字幕免费电影 | 久久久福利| 综合网天天 | 波多野结衣视频一区 | 成人免费观看在线视频 | 国产精品igao视频网入口 | 亚洲精品国产精品国自产 | 天天色天天综合 | 国产精品久久久久久久久久免费 | 中文在线8新资源库 | 99色婷婷| 国产成人久久精品一区二区三区 | 亚洲一区二区精品3399 | 又黄又爽又湿又无遮挡的在线视频 | 成人黄色一级视频 | 午夜精品视频一区二区三区在线看 | 成人av地址| 日韩在线观看一区二区 | 国产不卡免费 | 伊人五月天 | 亚洲午夜av | 日韩视频一 | 国产精品福利小视频 | 中文字幕在线第一页 | 国产精品综合久久久久 | 久久久久久久久久久久电影 | 永久精品视频 | 91精品视屏 | 久久激情小说 | 午夜在线免费观看视频 | 国产手机在线观看 | 国产一级一片免费播放放 | 日本中出在线观看 | 国产精品成人久久久 | 亚洲欧美视屏 | 亚洲精品在线免费看 | 日韩久久午夜一级啪啪 | 亚洲精品一区二区久 | 高清视频一区 | 免费视频成人 | 免费在线播放av电影 | 久久99精品久久久久久秒播蜜臀 | 久精品视频在线 | 人人爽久久久噜噜噜电影 | 国产高清在线a视频大全 | 久久婷婷一区二区三区 | 国内精品久久久久影院日本资源 | 在线观看的av| 精品av在线播放 | 国产专区视频在线观看 | 欧美日韩性 | av成人免费| 日韩欧美视频二区 | 超碰个人在线 | 天操夜夜操 | 91爱爱电影 | 欧美成人xxxx | 高清av免费观看 | 91大神精品视频在线观看 | 日韩中文字幕国产精品 | 欧美人人| 在线观看免费福利 | 亚洲精品视频在线播放 | 免费看黄色小说的网站 | 久久在线视频精品 | 成人a级网站| 亚洲精品乱码久久久久久高潮 | 999国内精品永久免费视频 | 日韩欧美不卡 | 国产免费av一区二区三区 | 2022国产精品视频 | 天天射色综合 | 欧美成人精品欧美一级乱黄 | 91尤物国产尤物福利在线播放 | 国产精品一区二区吃奶在线观看 | 欧美天天综合网 | 欧美整片sss | 99久久精品网 | 波多野结衣电影一区二区三区 | 久久亚洲私人国产精品va | 色视频成人在线观看免 | 在线观看中文字幕视频 | 另类老妇性bbwbbw高清 | 天天干天天干天天干天天干天天干天天干 | 夜夜夜夜夜夜操 | 日韩欧美xxx| 伊人天堂久久 | 日女人电影 | 亚洲黄色av网址 | 日韩av男人的天堂 | 亚洲精品一区二区网址 | 黄色亚洲片 | 色综合天天射 | 超碰在线资源 | 99久久夜色精品国产亚洲 | 最近中文字幕免费av | 毛片播放网站 | 在线不卡中文字幕播放 | 色鬼综合网 | 欧美与欧洲交xxxx免费观看 | 毛片黄色一级 | 国产一区在线视频播放 | a视频在线观看免费 | 狠狠色伊人亚洲综合成人 | 在线视频成人 | h网站免费在线观看 | 天天干夜夜爽 | 久久久久久国产精品久久 | 绯色av一区| 人人澡人 | 天天操夜夜操国产精品 | 日韩久久网站 | 日韩免费在线视频观看 | 免费在线观看日韩 | 国产精品一区二区麻豆 | 国产专区精品视频 | 天天干天天操天天拍 | 欧美激情视频一区二区三区 | 久久久久久在线观看 | 91麻豆精品 | 国产91丝袜在线播放动漫 | 亚洲免费一级 | 911免费视频| 日韩久久午夜一级啪啪 | 欧美日韩啪啪 | 91视频免费国产 | 亚洲欧美视频网站 | 欧美一区在线看 | 国产精品美女久久久久久 | 国产精品自拍av | av资源免费观看 | 日韩激情综合 | 国产精品情侣视频 | 亚洲男人天堂a | 丁香婷婷综合五月 | 在线观看国产麻豆 | 国产日韩欧美自拍 | 国产3p视频| 人人爽人人爽人人片 | 精品久久99| 久久99国产精品久久 | 亚洲欧美经典 | 中文字幕一区二区三区在线播放 | 午夜精品99久久免费 | 丁香婷婷久久 | 欧美va在线观看 | 97精品国产一二三产区 | 高清国产一区 | 91探花视频 | 久久九九影视网 | 日本三级香港三级人妇99 | 亚洲国产影院av久久久久 | 日韩欧美一区二区不卡 | 国产一区二区在线观看视频 | 成人性生爱a∨ | 成人网在线免费视频 | 日韩高清免费无专码区 | 激情久久五月天 | 色多多污污 | 日韩免费一二三区 | 成人全视频免费观看在线看 | 成人黄色小说视频 | 国产成人久久精品亚洲 | 91视频免费看网站 | 日韩电影在线视频 | 一区二区三区四区五区在线视频 | 免费观看性生活大片3 | 日本一区二区免费在线观看 | 四虎成人网 | 成人黄大片视频在线观看 | 久久久久 免费视频 | 国内外成人免费在线视频 | 又黄又爽又无遮挡的视频 | 国产成人av综合色 | 国产精品麻豆三级一区视频 | 免费在线观看成年人视频 | 亚洲一区二区三区四区精品 | 91在线精品一区二区 | 久久综合欧美精品亚洲一区 | 久色免费视频 | 亚州av成人 | 色婷婷成人网 | 免费91在线观看 | 午夜丰满寂寞少妇精品 | 中文在线字幕免 | 久久久久亚洲精品 | 99久久精品无码一区二区毛片 | 丝袜网站在线观看 | 亚洲欧美少妇 | 久久爱资源网 | av在线播放一区二区三区 | 91九色精品女同系列 | 超碰在线观看97 | 国产91av视频在线观看 | 黄色大片国产 | 久久久国产精品免费 | 九九在线精品视频 | 亚洲人成综合 | 成人电影毛片 | 搡bbbb搡bbb视频 | 天天插天天干天天操 | 欧美日韩另类在线观看 | 狠狠干狠狠艹 | av电影免费观看 | 日韩视频免费观看高清 | 欧美黄色特级片 | 99 视频 高清| 视频福利在线 | 国产在线精品一区 | 精品久久久久久久久久久久久久久久久久 | 一本一道久久a久久精品蜜桃 | 国产亚洲aⅴaaaaaa毛片 | 这里只有精品视频在线 | 伊色综合久久之综合久久 | 精品国产诱惑 | 四川bbb搡bbb爽爽视频 | 国产亚洲人 | 99久久www| 国产精品一区二区免费视频 | 久久精品国产美女 | 欧美美女激情18p | 99久久精品免费看国产免费软件 | 精品av在线播放 | 国产精品第10页 | 99久久精品免费看国产一区二区三区 | 国产精品刺激对白麻豆99 | 激情婷婷在线观看 | www久久久久 | 精品久久久久久亚洲综合网站 | 欧美黄色成人 | 99久久精品国产观看 | 成年人在线电影 | 国产精品一区二区果冻传媒 | 夜夜夜夜爽| 精品久久久久久久久久国产 | 国产一级片在线播放 | 亚洲一区精品人人爽人人躁 | 2020天天干夜夜爽 | 91女神的呻吟细腰翘臀美女 | 久草香蕉在线 | 中文字幕黄色网址 | 欧美日韩精品二区第二页 | 久久久www成人免费毛片 | 麻豆精品视频 | 国产不卡在线播放 | 亚洲,国产成人av | 香蕉影院在线播放 | av免费观看网站 | 91视频 - 114av| 国产精品久久久久久av | 成人精品视频久久久久 | 黄色免费在线视频 | 成人精品一区二区三区电影免费 | 99精品观看| 国产中文字幕久久 | 一本一本久久aa综合精品 | 成年人看片网站 | 91网址在线| 日本久久高清视频 | 免费观看国产精品视频 | 天天干天天草天天爽 | 黄色aaaaa| 久草视频在线免费播放 | 精品视频资源站 | 国产又粗又猛又黄又爽 | 黄色成人av | 亚洲最大av | 香蕉网址| 久久精品99国产国产精 | 国产在线观看xxx | 亚洲激情免费 | 色综合久久网 | 成人免费xyz网站 | 免费特级黄毛片 | 91精品区 | 久久男人免费视频 | 成人在线观看影院 | 久久免费久久 | 亚州性色 | 欧美色噜噜噜 | 最近免费中文字幕mv在线视频3 | 人人揉人人揉人人揉人人揉97 | 午夜精品成人一区二区三区 | 国产精品99久久免费观看 | 日韩高清精品一区二区 | 成人全视频免费观看在线看 | 国产福利91精品 | 96精品高清视频在线观看软件特色 | 国产性xxxx | 欧美日韩网站 | 在线视频精品 | 免费久久精品视频 | 久久国产视屏 | 97在线视 | 99在线看 | 国产日韩欧美在线影视 | 婷婷www | 精品视频资源站 | 福利视频网址 | 国产日韩精品一区二区三区 | 国产精品99久久久久 | 色网站在线免费观看 | 日韩手机视频 | 日韩在线观看一区二区 | 91成人欧美| 黄色免费大全 | 午夜久操 | 综合婷婷久久 | 五月综合激情 | 亚州成人av在线 | av+在线播放在线播放 | 黄毛片在线观看 | 一本一本久久a久久精品综合小说 | 五月天婷婷免费视频 | 欧美一级黄色片 | 午夜日b视频| 4438全国亚洲精品观看视频 | 天天爱天天插 | 在线精品视频免费播放 | 国产一级片播放 | 国产 日韩 欧美 自拍 | 成年美女黄网站色大片免费看 | 亚洲乱码一区 | 天天人人 | www色| 国产黄色网 | 国产字幕av | 午夜精品成人一区二区三区 | 天天做日日爱夜夜爽 | 国产小视频在线 | 国产精品毛片久久久久久久 | 国产欧美精品一区二区三区 | 午夜久久久久久久久久久 | 国产高清成人av | 成人三级av | 免费亚洲成人 | 久久久久久久综合色一本 | 精品久久久久久久久久岛国gif | 视频三区| 国产精品麻 | 欧美激情综合五月 | 激情婷婷综合网 | 超碰在线成人 | 天天综合网在线 | 欧美精品亚洲二区 | 国产高清视频在线观看 | 日韩有码中文字幕在线 | 久久99精品久久久久久秒播蜜臀 | 精品国产一区二区三区久久影院 | 九九热只有这里有精品 | 国内免费久久久久久久久久久 | 在线观看中文字幕一区二区 | av资源免费观看 | 日韩丝袜在线 | 中文区中文字幕免费看 | 99久久成人| 日本福利视频在线 | 黄p网站在线观看 | 久草综合视频 | 久久99精品国产一区二区三区 | 一区二区三区在线免费播放 | 午夜美女福利直播 | 免费黄色av电影 | 日韩黄色免费 | 国产亚洲精品久久久网站好莱 | 91久久奴性调教 | 亚洲国产一二三 | 色婷婷丁香 | 狠狠狠色丁香婷婷综合久久88 | 国产伦精品一区二区三区照片91 | 国产精品免费人成网站 | 久草视频在线新免费 | 日韩一区二区久久 | 成年一级片 | 999久久久国产精品 高清av免费观看 | 黄色软件在线看 | 国产高清视频色在线www | 在线免费观看成人 | 丰满少妇在线观看 | 一区二区三区动漫 | 国产精品mv在线观看 | 日批视频国产 | 97视频网站 | 国产一区二区精品久久 | 中文字幕日本特黄aa毛片 | 亚洲天堂毛片 | 精品国产一区二区三区噜噜噜 | 五月开心六月伊人色婷婷 | 色综合色综合久久综合频道88 | 93久久精品日日躁夜夜躁欧美 | 日韩视频在线观看视频 | 日本中文字幕电影在线免费观看 | 天天干婷婷 | 中文字幕制服丝袜av久久 | 欧美十八 | 免费观看黄色12片一级视频 | 九月婷婷人人澡人人添人人爽 | 婷婷激情影院 | 亚洲激情视频 | 欧美一级艳片视频免费观看 | 91秒拍国产福利一区 | 欧洲性视频 | 日韩精品一区二区三区三炮视频 | 久久成人资源 | 精品国产一区二区三区久久久蜜月 | 成+人+色综合 | 五月天久久婷婷 | 字幕网av| 一区免费观看 | 天天插天天爽 | av中文字幕网站 | 欧美成年人在线视频 | 日韩欧美国产视频 | 免费激情在线电影 | 中文字幕乱码亚洲精品一区 | 9999免费视频 | 国产 一区二区三区 在线 | 亚洲四虎在线 | 国产高清免费观看 | 国产精品婷婷午夜在线观看 | 久久久亚洲影院 | 手机在线中文字幕 | 欧美成人精品三级在线观看播放 | 国产一区二区视频在线播放 | 99在线国产 | 精品99视频| 毛片一区二区 | 五月天视频网站 | 精品国产精品一区二区夜夜嗨 | 九草在线观看 | 天天夜夜狠狠操 | 色婷婷激情电影 | 国产特级毛片aaaaaaa高清 | 国外成人在线视频网站 | 激情欧美一区二区三区免费看 | 国产精品美女久久久久久久久 | 国产成人精品一区二区三区网站观看 | 青青河边草观看完整版高清 | 精品国产乱码久久久久久三级人 | 久久久久久久久久久久久9999 | 国产在线精品播放 | 国产99久 | 国产婷婷精品av在线 | 亚洲欧美一区二区三区孕妇写真 | 黄av免费 | 久久99精品久久久久久久久久久久 | av五月婷婷 | 欧美色图30p | 亚洲网站在线 | 91高清不卡 | 日本黄色免费播放 | 精品一区在线 | 99色在线视频 | 国产美女精品视频 | 精品久久一级片 | 久久久久久毛片精品免费不卡 | 成人中文字幕+乱码+中文字幕 | 午夜久操 | 2019中文| 国产精品高清av | 九九热有精品 | 国色综合 | 亚洲高清资源 | 精品1区2区| 麻豆视频免费入口 | 精品国产一区二区三区日日嗨 | 国产精品久久婷婷六月丁香 | 黄色精品久久久 | 欧美在线视频不卡 | 中国一级片视频 | 99免费看片 | 特黄免费av | 久久国内精品99久久6app | 久草在线久 | 久久草精品 | 日韩另类在线 | 日韩视频在线播放 | 国产视频九色蝌蚪 | 久久精品99国产精品酒店日本 | 久久九九影视网 | 亚洲乱码在线观看 | 国产精品成人一区二区三区吃奶 | 91一区二区三区久久久久国产乱 | 日韩高清观看 | 亚洲91中文字幕无线码三区 | 最新极品jizzhd欧美 | 亚洲资源一区 | 国产人成精品一区二区三 | 久久伊人热| 91看片淫黄大片一级在线观看 | 亚洲国产精品电影 | 999在线精品 | 亚洲欧洲av| 亚洲成人动漫在线观看 | 91精品视频在线看 | 久久一区二区免费视频 | 亚洲国产99 | 黄色1级毛片 | 婷婷丁香花|