亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁技術文章
文章詳情頁

Android ServiceManager的啟動和工作原理

瀏覽:2日期:2022-09-20 09:27:11
ServiceManager啟動

所有的系統服務都是需要在ServiceManager中進行注冊的,而ServiceManager作為一個起始的服務,是通過init.rc來啟動的。

//systemcorerootdirinit.rc//啟動的服務,這里是用的服務名稱。服務名稱是在對應的rc文件中注冊并啟動的 start servicemanager

具體的服務信息是在servicemanger.rc命名并定義的

//frameworksnativecmdsservicemanagerservicemanager.rcservice servicemanager /system/bin/servicemanager class core animation user system //說明以用戶system身份運行 group system readproc //說明servicemanager是系統中的關鍵服務, //關鍵服務是不會退出的,如果退出了,系統就會重啟,當系統重啟時就會啟動用onrestart關鍵字修飾的進程, //比如zygote、media、surfaceflinger等等。 critical onrestart restart healthd onrestart restart zygote onrestart restart audioserver onrestart restart media onrestart restart surfaceflinger onrestart restart inputflinger onrestart restart drm onrestart restart cameraserver onrestart restart keystore onrestart restart gatekeeperd onrestart restart thermalservice ..

servicemanager的入口函數在service_manager.c中

//frameworksnativelibsbinderndkservice_manager.cppint main(int argc, char** argv){//binder_state結構體,用來存儲binder的三個信息 struct binder_state *bs;//打開binder驅動,并申請125k字節的內存空間 bs = binder_open(driver, 128*1024); ...//將自己注冊為Binder機制的管理者 if (binder_become_context_manager(bs)) { ALOGE('cannot become context manager (%s)n', strerror(errno)); return -1; } ...//啟動循環,等待并處理client端發來的請求 binder_loop(bs, svcmgr_handler); return 0;}

在main函數中主要做了3件事情。

打開驅動,并申請了128k字節大小的內存空間 將自己注冊為Binder機制的管理者 啟動循環,等待并處理Client端發來的請求 binder_open

//frameworksnativecmdsservicemanagerbinder.cstruct binder_state *binder_open(const char* driver, size_t mapsize){ struct binder_state *bs; struct binder_version vers; //申請對應的內存空間 bs = malloc(sizeof(*bs));//打開binder設備文件,這種屬于設備驅動的操作方法 bs->fd = open(driver, O_RDWR | O_CLOEXEC);//通過ioctl獲取binder的版本號 if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) || (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) { fprintf(stderr,'binder: kernel driver version (%d) differs from user space version (%d)n',vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION); goto fail_open; } bs->mapsize = mapsize;//mmap進行內存映射,將Binder設備文件映射到進程的對應地址空間,地址空間大小為128k//映射之后,會將地址空間的起始地址和大小保存到結構體中, bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); return bs;}

binder_opende的主要功能是打開了Binder的驅動文件,并將文件進行了mmap映射,并將對應的地址空間保存到了結構體中。

binder_become_context_manager

//frameworksnativecmdsservicemanagerbinder.cint binder_become_context_manager(struct binder_state *bs){ return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);}

ioctl會調用Binder驅動的binder_ioctl函數,去注冊成為管理者。

binder_loop

將servicemanger注冊為Binder的上下文管理者后,它就是Binder機制的“大總管”了,它會在系統運行期間處理Client端的請求,因為請求的時間不確定性,這里采用了無限循環來實現。也就是binder_loop

//frameworksnativecmdsservicemanagerbinder.cvoid binder_loop(struct binder_state *bs, binder_handler func){ int res; struct binder_write_read bwr; uint32_t readbuf[32]; bwr.write_size = 0; bwr.write_consumed = 0; bwr.write_buffer = 0;//當前線程注冊為Binder的指令 readbuf[0] = BC_ENTER_LOOPER;//將BC_ENTER_LOOPER指令寫入到Binder驅動,//將當前的ServiceManager線程注冊為了一個Binder線程(注意ServiceManager本身也是一個Binder線程)。//注冊為Binder線程之后,就可以處理進程間的請求了 binder_write(bs, readbuf, sizeof(uint32_t));//不斷的循環遍歷 for (;;) { bwr.read_size = sizeof(readbuf); bwr.read_consumed = 0; bwr.read_buffer = (uintptr_t) readbuf;//使用BINDER_WRITE_READ指令查詢Binder驅動中是否有請求。//如果有請求,就走到下面的binder_parse部分處理,如果沒有,當前的ServiceManager線程就會在Binder驅動中水命,等待新的進程間請求 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);//走到這里說明有請求信息。將請求的信息用binder_parse來處理,處理方法是func res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func); }}

servicemanager會先將自己注冊為一個Binder線程。因為只有注冊成為Binder服務之后才能接收進程間的請求。而注冊為Binder服務的指令是BC_ENTER_LOOPER。然后通過**binder_write()**方法寫入到binder驅動。

//frameworksnativecmdsservicemanagerbinder.cint binder_write(struct binder_state *bs, void *data, size_t len){ struct binder_write_read bwr; int res; bwr.write_size = len; bwr.write_consumed = 0; bwr.write_buffer = (uintptr_t) data; bwr.read_size = 0; bwr.read_consumed = 0; bwr.read_buffer = 0;//BINDER_WRITE_READ既可以讀也可以寫。關鍵在于read_size和write_size。//如果write_size>0。則是寫。如果read_size>0則是讀。//如果都大于0,則先寫,再讀 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); if (res < 0) { fprintf(stderr,'binder_write: ioctl failed (%s)n',strerror(errno)); } return res;}系統服務注冊

在Android中,每個進程獲取系統提供的各種系統服務(AMS,PMS,WMS等)都是需要通過ServiceManager才可以。而這些系統服務進行Binder注冊,也需要獲取ServiceManager服務才可以。在剛才我們講過,ServiceManager會將自己也注冊成為一個Binder服務。

這里我們以SurfaceFling獲取ServiceManager服務為例來看一下是如何獲取的。

//frameworksnativeservicessurfaceflingermain_surfaceflinger.cpp#include <binder/IServiceManager.h>int main(int, char**) { .... //獲取一個SM對象,相當于是new BpServiceManager(new BpBinder(0)) sp<IServiceManager> sm(defaultServiceManager());//向ServiceManager注冊SurfaceFling服務 sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false, IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);//在SurfaceFlinger調用init方法的時候,會初始化Display的相關信息 startDisplayService(); // dependency on SF getting registered above ... return 0;}

系統服務的注冊過程主要有2點

獲取ServiceManager所對應的Binder對象。 通過addService注冊為系統服務。 ServiceManager的Binder對象獲取

**defaultServiceManager()**方法就是用來獲取ServiceManager服務的Binder對象。

defaultServiceManager

//frameworksnativelibsbinderIServiceManager.cppsp<IServiceManager> defaultServiceManager(){ if (gDefaultServiceManager != nullptr) return gDefaultServiceManager; { AutoMutex _l(gDefaultServiceManagerLock);/* * 1. ProcessState::self()->getContextObject(NULL): 返回的是一個 BpBinder. ServiceManager 的 desc 默認為0. * 2. interface_cast 就是將 BpBinder 封裝為 IServiceManager,這樣可以直接調用 IServiceManager 的接口.*//* * 這里,有一個設計思想. * 1. defaultServiceManager 首先實例化 BpBinder. * 2. interface_cast 就是 實例化 BpXXX,并將 BpBinder 交給其管理. * * Proxy 端的用戶無法直接看到 BpBinder , BpBinder 由 BpXXX 持有.用戶本身不關心 BpBinder 的能力,只關心 IXXX 定義的 接口. * 所以這里很好的進行了封裝.*/ while (gDefaultServiceManager == nullptr) {//如果不為空,表示設置過了,直接返回 //嘗試不斷的獲取ServiceManager對象,如果獲取不到,就sleep(1), //這里之所以會獲取不到,是因為ServiceManager和一些通過init.rc啟動的服務是同時啟動的,不能保證ServiceManager能夠優先啟動完成。 //所以會存在獲取ServiceManager的時候獲取不到。 gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(nullptr)); if (gDefaultServiceManager == nullptr)sleep(1); } } return gDefaultServiceManager;}

這里會直接調用**ProcessState::self()->getContextObject(nullptr)**來獲取對應的服務。

ProcessState::self()->getContextObject(NULL): 返回的是一個 BpHwBinder。ServiceManager 的 desc 默認為0。 interface_cast 就是將 BpBinder 封裝為 IServiceManager

ProcessState::self()

//systemlibhwbinderProcessState.cpp//返回一個ProcessStatesp<ProcessState> ProcessState::self(){ Mutex::Autolock _l(gProcessMutex); if (gProcess != nullptr) { return gProcess; } gProcess = new ProcessState(kDefaultDriver); return gProcess;}

這里會返回一個ProcessState對象。

getContextObject

//systemlibhwbinderProcessState.cppsp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/){ //傳入的參數是handle。0, return getStrongProxyForHandle(0);}sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle){ handle_entry* e = lookupHandleLocked(handle); if (e != nullptr) { IBinder* b = e->binder; if (b == nullptr || !e->refs->attemptIncWeak(this)) {//如果b為空,那么創建一個BpHwBinder b = new BpHwBinder(handle); e->binder = b; if (b) e->refs = b->getWeakRefs(); result = b; } else { result.force_set(b); e->refs->decWeak(this); } } return result;}

當不存在的時候,這里會創建一個BpHwBinder對象。所以可以理解為最后我們返回的是一個BpBinder對象

這里,有一個設計思想:

defaultServiceManager 首先實例化 BpBinder。 interface_cast 就是 實例化 BpXXX,并將 BpBinder交給其管理。

Proxy 端的用戶無法直接看到 BpBinder, BpBinder 由 BpXXX 持有.用戶本身不關心 BpBinder的能力,只關心 IXXX 定義的 接口。所以這里很好的進行了封裝。

回到前文的defaultServiceManger方法中,將返回值帶入,可以得到

//注意,方法中傳入的handle為0,所以BpBinder參數為0gDefaultServiceManager = interface_cast<IServiceManager>(new BpBinder(0));

interface_cast

//frameworksnativeincludebinderIInterface.hinline sp<INTERFACE> interface_cast(const sp<IBinder>& obj){ return INTERFACE::asInterface(obj);}//INTERFACE帶入為IServiceManager之后,得到的代碼為inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj){ return IServiceManager::asInterface(obj);//靜態方法所以直接調用}

調用IServiceManager接口的成員函數asInterface,將一個句柄值為0的Binder代理對象封裝為一個ServiceManger代理對象。將一個句柄值為0的Binder代理對象封裝為一個ServiceManger代理對象。

這里 IServiceManager接口的成員函數asInterface是通過宏IMPLEMENT_META_INTERFACE實現,如下所示:

#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME) #endif#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME) ::android::sp<I##INTERFACE> I##INTERFACE::asInterface( const ::android::sp<::android::IBinder>& obj) { android::sp<I##INTERFACE> intr; if (obj != nullptr) { intr = static_cast<I##INTERFACE*>( obj->queryLocalInterface( I##INTERFACE::descriptor).get()); if (intr == nullptr) { intr = new Bp##INTERFACE(obj); } } return intr; }

帶入IServiceManager之后的代碼為:

android::sp<IServiceManager> IIServiceManager::asInterface(const android::sp<android::IBinder>& obj) { android::sp<IServiceManager> intr; if (obj != NULL) { intr = static_cast<IIServiceManager*>( obj->queryLocalInterface(IServiceManager::descriptor).get());//返回NULLif (intr == NULL) {intr = new BpServiceManager(obj); //創建了ServiceManager代理對象 } }return intr; }

到這里為止,我們創建了一個BpIServiceManager對象,并將他的接口IServiceManager返回給了調用者。

整體的邏輯可以理解為:new BpServiceManager(new BpBinder())。當然了,這只是簡化之后的代碼,其內部復雜的邏輯現在可以暫不考慮。整體流程如下:

Android ServiceManager的啟動和工作原理

添加Service

客戶端請求

當獲取到ServiceManager服務之后,就可以使用addService方法來進行服務的注冊了。在獲取服務的時候,最終返回的是BpServiceManager對象,所以這里我們可以直接找到對應的添加服務方法

virtual status_t addService(const String16& name, const sp<IBinder>& service,bool allowIsolated, int dumpsysPriority) { Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); data.writeStrongBinder(service); data.writeInt32(allowIsolated ? 1 : 0); data.writeInt32(dumpsysPriority); status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); return err == NO_ERROR ? reply.readExceptionCode() : err; }

BpServiceManager的構造函數傳入的了BpBinder對象,這里的remote()方法其實就是BpBinder對象。

status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){ //如果binder已經died,則不會返回數據 if (mAlive) { ...//調用IPCThreadState的transact方法。 status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags); if (status == DEAD_OBJECT) mAlive = 0; return status; } return DEAD_OBJECT;}

這里調用了IPCThreadState的transact方法將對應的數據寫入到了Binder驅動了。當Binder驅動接收到注冊服務的信息的時候,就會將對應的服務注冊到ServiceManager中。我們可以看下傳遞的參數:

mHandle:0,表示要處理該請求的進程號,ServiceManager在注冊的時候,其對應的進程號是0。所以處理請求的也就是ServiceManager進程。 code:參數是ADD_SERVICE_TRANSACTION。 data:包含了要添加的進程相關信息:包括名稱、是否單獨運行等等相關信息

ServiceManager處理請求

當客戶端發送請求之后,我們的ServiceManger就可以接收到消息,并且進行消息的處理了。在ServiceManager的啟動中我們了解到,當ServiceManger啟動之后,會調用binder_looper來不斷的循環,檢測是否接收到對應的數據信息。

這個功能是在binder_loop()方法的入參中的svcmgr_handler來實現的。

//frameworksnativelibsbinderndkservice_manager.cppint main(int argc, char** argv){...//啟動循環,等待并處理client端發來的請求 binder_loop(bs, svcmgr_handler); ...}

svcmgr_handler就是我們具體的請求處理方法。

//frameworksnativecmdsservicemanagerservice_manager.cint svcmgr_handler(struct binder_state *bs, struct binder_transaction_data_secctx *txn_secctx, struct binder_io *msg, struct binder_io *reply){ ... struct binder_transaction_data *txn = &txn_secctx->transaction_data; ...//根據傳輸的不同類型來進行處理。 switch(txn->code) { case SVC_MGR_ADD_SERVICE://添加服務 //進行服務的添加 do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,txn->sender_pid, (const char*) txn_secctx->secctx) ... } int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle, uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid, const char* sid) { struct svcinfo *si; //ALOGI('add_service(’%s’,%x,%s) uid=%dn', str8(s, len), handle, // allow_isolated ? 'allow_isolated' : '!allow_isolated', uid); //服務的名稱長度不能超過127字節 if (!handle || (len == 0) || (len > 127)) return -1;//最終調用selinux_check_access方法,會進行權限的檢測,檢查服務是否有進行服務注冊 if (!svc_can_register(s, len, spid, sid, uid)) { ALOGE('add_service(’%s’,%x) uid=%d - PERMISSION DENIEDn', str8(s, len), handle, uid); return -1; }//查詢是否已經有包含了name的svcinfo si = find_svc(s, len); if (si) { if (si->handle) { ALOGE('add_service(’%s’,%x) uid=%d - ALREADY REGISTERED, OVERRIDEn', str8(s, len), handle, uid);//已經注冊了,釋放相應的服務 svcinfo_death(bs, si); }//更新服務的handle si->handle = handle; } else {//申請內存 si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t)); si->handle = handle; si->len = len; memcpy(si->name, s, (len + 1) * sizeof(uint16_t)); si->name[len] = ’0’; si->death.func = (void*) svcinfo_death; si->death.ptr = si; si->allow_isolated = allow_isolated; si->dumpsys_priority = dumpsys_priority;//將其注冊到服務列表svclist中,這里使用的鏈表來保存數據 si->next = svclist; svclist = si; }//以handle為目標,發送BC_ACQUIRE指令。 binder_acquire(bs, handle);//以handle為目標,發送BC_REQUEST_DEATH_NOTIFICATION指令。 binder_link_to_death(bs, handle, &si->death); return 0;}

當拿到請求信息之后,ServiceManager會生成對應的svcinfo對象,將其保存到服務列表svclist中。

整體流程如下:

Android ServiceManager的啟動和工作原理

我們也可以從另一個維度去看看Binder的具體

系統服務獲取

對于Servie服務的獲取,其實也是答題思路也是相同的。顯示獲取ServiceManager的Binder對象,然后服務端發送獲取某項服務的請求,ServiceManager來進行處理。

這里我們只看一下ServiceManager接收到服務獲取的處理機制。也是在**svcmgr_handler()**中。

//frameworksnativecmdsservicemanagerservice_manager.cint svcmgr_handler(struct binder_state *bs, struct binder_transaction_data_secctx *txn_secctx, struct binder_io *msg, struct binder_io *reply){ ... struct binder_transaction_data *txn = &txn_secctx->transaction_data; ...//根據傳輸的不同類型來進行處理。 switch(txn->code) { case SVC_MGR_GET_SERVICE://獲取服務 case SVC_MGR_CHECK_SERVICE: s = bio_get_string16(msg, &len); if (s == NULL) {return -1; } //根據pid,uid來獲取服務對應的handle值 handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid, (const char*) txn_secctx->secctx); if (!handle)break; //返回服務對應的handle bio_put_ref(reply, handle); return 0;}

這里主要做了2個操作:

從服務列表中獲取到對應的服務的handle 將handle寫入到要返回的reply數據中。 do_find_service

//frameworksnativecmdsservicemanagerservice_manager.c //獲取對應的服務uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid, const char* sid){//獲取對應的服務 struct svcinfo *si = find_svc(s, len); if (!si || !si->handle) { return 0; } if (!si->allow_isolated) { // If this service doesn’t allow access from isolated processes, // then check the uid to see if it is isolated. uid_t appid = uid % AID_USER;//檢查服務是否是允許孤立于進程而單獨存在的 if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) { return 0; } }//檢測是否有selinx權限。 if (!svc_can_find(s, len, spid, sid, uid)) { return 0; }//返回服務的handle return si->handle;}bio_put_ref

當獲取到服務之后handle之后,會調用**bio_put_ref()**方法將服務對應的handle寫入到返回的數據中。

//frameworksnativecmdsservicemanagerservice_manager.cvoid bio_put_ref(struct binder_io *bio, uint32_t handle){ struct flat_binder_object *obj;//申請對應的地址空間 if (handle) obj = bio_alloc_obj(bio); else obj = bio_alloc(bio, sizeof(*obj)); if (!obj) return; obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;//類型是BINDER_TYPE_HANDLE obj->hdr.type = BINDER_TYPE_HANDLE;//記錄handle obj->handle = handle; obj->cookie = 0;}

對于服務的獲取,肯定是需要將reply的數據寫回到請求服務的進程的。這時候就需要回到我們在binder_loop()函數了。在該函數中,存在一個binder_parse(),在這個方法里面會處理請求信息,并將reply信息通過binder驅動發送給客戶端。

binder_parse

//frameworksnativecmdsservicemanagerbinder.cint binder_parse(struct binder_state *bs, struct binder_io *bio, uintptr_t ptr, size_t size, binder_handler func){ ... case BR_TRANSACTION: { ...//調用func函數res = func(bs, txn, &msg, &reply);if (txn->flags & TF_ONE_WAY) { binder_free_buffer(bs, txn->data.ptr.buffer);} else {//發送協議指令給Binder驅動,向Client端發送reply binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);} ... return r;}

當調用了func函數,有對應返回信息之后,會通過binder_send_reply()方法,將reply數據信息發送給client端。

void binder_send_reply(struct binder_state *bs, struct binder_io *reply, binder_uintptr_t buffer_to_free, int status){ struct { uint32_t cmd_free; binder_uintptr_t buffer; uint32_t cmd_reply; struct binder_transaction_data txn; } __attribute__((packed)) data; data.cmd_free = BC_FREE_BUFFER; data.buffer = buffer_to_free;//返回指令 data.cmd_reply = BC_REPLY; data.txn.target.ptr = 0; data.txn.cookie = 0; data.txn.code = 0; if (status) { data.txn.flags = TF_STATUS_CODE; data.txn.data_size = sizeof(int); data.txn.offsets_size = 0; data.txn.data.ptr.buffer = (uintptr_t)&status; data.txn.data.ptr.offsets = 0; } else {//svcmgr_handler執行成功,將reply數據組裝到txn中 data.txn.flags = 0; data.txn.data_size = reply->data - reply->data0; data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0); data.txn.data.ptr.buffer = (uintptr_t)reply->data0; data.txn.data.ptr.offsets = (uintptr_t)reply->offs0; }//發送數據 binder_write(bs, &data, sizeof(data));}總結

ServiceManager是一個守護進程,負責管理系統中的所有服務信息。通過一個鏈表來保存了所有注冊過的信息。而且其本身也是一個服務,在通過Binder驅動將其注冊為守護進程之后,會將自己也注冊為一個服務,供其他服務調用。

Android ServiceManager的啟動和工作原理

以上就是Android ServiceManager的啟動和工作原理的詳細內容,更多關于Android ServiceManager的資料請關注好吧啦網其它相關文章!

標簽: Android
相關文章:
主站蜘蛛池模板: 高清一级毛片免免费看 | 在线观看国产一区二区三区99 | 一区二区三区日韩精品 | 色盈盈影院| 婷婷伊人久久 | 欧美精品在线一区二区三区 | 嫩草视频在线观看 | 国产人成精品免费视频 | 美女吊黑视频在线观看 | 国产午夜精品理论片久久影视 | 欧美一级特黄高清免费 | 日韩一区二三区无 | 在线播放黄色网址 | 欧美性生活视频播放 | 美国一级片视频 | 国产日韩欧美成人 | 香港经典a毛片免费观看看 香港黄页亚洲一级 | 特黄一级真人毛片 | 一级女性全黄生活片看看 | 最新欧美精品一区二区三区不卡 | 美女喷水视频在线观看 | 久久国产自偷自免费一区100 | 色综合久久98天天综合 | 最全精品自拍视频在线 | 中文字幕亚洲综合 | 中文字幕亚洲精品日韩精品 | 亚洲邪恶天堂影院在线观看 | 日韩三级毛片 | 久久精品国产精品亚洲 | 96精品 | 国产精品亚洲欧美云霸高清 | 看黄色一级片子 | 国产亚洲精品美女2020久久 | 在线视频免费观看短视频 | 国产一级淫片a免费播放口欧美 | 亚洲最大成人综合网 | 啪啪91视频 | 亚洲精品一区二区观看 | 在线免费观看色视频 | 亚洲精品永久www嫩草 | 国产人成午夜免视频网站 |