HIDL學(xué)習(xí)筆記之HIDL C++(第一天)

最近在學(xué)習(xí)HIDL收叶,有很多的疑惑,在這里記錄一下玄组,加深自己的理解滔驾,以下部分大多來(lái)自官網(wǎng)。
官網(wǎng):https://source.android.com/devices/architecture/hidl

HIDL定義

HAL 接口定義語(yǔ)言(簡(jiǎn)稱 HIDL俄讹,發(fā)音為“hide-l”)是用于指定 HAL 和其用戶之間的接口的一種接口描述語(yǔ)言 (IDL)哆致。HIDL 允許指定類型和方法調(diào)用(會(huì)匯集到接口和軟件包中)。從更廣泛的意義上來(lái)說(shuō)患膛,HIDL 是用于在可以獨(dú)立編譯的代碼庫(kù)之間進(jìn)行通信的系統(tǒng)摊阀。

HIDL 旨在用于進(jìn)程間通信 (IPC)。進(jìn)程之間的通信經(jīng)過(guò) Binder 化。對(duì)于必須與進(jìn)程相關(guān)聯(lián)的代碼庫(kù)胞此,還可以使用直通模式(在 Java 中不受支持)臣咖。

HIDL 可指定數(shù)據(jù)結(jié)構(gòu)和方法簽名,這些內(nèi)容會(huì)整理歸類到接口(與類相似)中漱牵,而接口會(huì)匯集到軟件包中夺蛇。盡管 HIDL 具有一系列不同的關(guān)鍵字,但 C++ 和 Java 程序員對(duì) HIDL 的語(yǔ)法并不陌生酣胀。此外刁赦,HIDL 還使用 Java 樣式的注釋。

HIDL C++

Android O 對(duì) Android 操作系統(tǒng)的架構(gòu)重新進(jìn)行了設(shè)計(jì)闻镶,以在獨(dú)立于設(shè)備的 Android 平臺(tái)與特定于設(shè)備和供應(yīng)商的代碼之間定義清晰的接口甚脉。Android 已經(jīng)以 HAL 接口的形式(在 hardware/libhardware 中定義為 C 標(biāo)頭)定義了許多此類接口。HIDL 將這些 HAL 接口替換為穩(wěn)定的帶版本接口铆农,它們可以是采用 C++(如下所述)或 Java 的客戶端和服務(wù)器端 HIDL 接口牺氨。

本部分中的幾頁(yè)內(nèi)容介紹了 HIDL 接口的 C++ 實(shí)現(xiàn),其中詳細(xì)說(shuō)明了 hidl-gen 編譯器基于 HIDL .hal 文件自動(dòng)生成的文件墩剖,這些文件如何打包猴凹,以及如何將這些文件與使用它們的 C++ 代碼集成。

HIDL 設(shè)計(jì)

HIDL 的目標(biāo)是涛碑,框架可以在無(wú)需重新構(gòu)建 HAL 的情況下進(jìn)行替換精堕。HAL 將由供應(yīng)商或 SOC 制造商構(gòu)建,放置在設(shè)備的 /vendor 分區(qū)中蒲障,這樣一來(lái)歹篓,框架就可以在其自己的分區(qū)中通過(guò) OTA 進(jìn)行替換,而無(wú)需重新編譯 HAL揉阎。

HIDL 設(shè)計(jì)在以下方面之間保持了平衡:

  • 互操作性庄撮。在可以使用各種架構(gòu)、工具鏈和編譯配置來(lái)編譯的進(jìn)程之間創(chuàng)建可互操作的可靠接口毙籽。HIDL 接口是分版本的洞斯,發(fā)布后不得再進(jìn)行更改。
  • 效率坑赡。HIDL 會(huì)嘗試盡可能減少?gòu)?fù)制操作的次數(shù)烙如。HIDL 定義的數(shù)據(jù)以 C++ 標(biāo)準(zhǔn)布局?jǐn)?shù)據(jù)結(jié)構(gòu)傳遞至 C++ 代碼,無(wú)需解壓毅否,可直接使用亚铁。此外,HIDL 還提供共享內(nèi)存接口螟加;由于 RPC 本身有點(diǎn)慢徘溢,因此 HIDL 支持兩種無(wú)需使用 RPC 調(diào)用的數(shù)據(jù)傳輸方法:共享內(nèi)存和快速消息隊(duì)列 (FMQ)吞琐。
  • 直觀。通過(guò)僅針對(duì) RPC 使用 in 參數(shù)然爆,HIDL 避開了內(nèi)存所有權(quán)這一棘手問(wèn)題(請(qǐng)參閱 Android 接口定義語(yǔ)言 (AIDL))站粟;無(wú)法從方法高效返回的值將通過(guò)回調(diào)函數(shù)返回。無(wú)論是將數(shù)據(jù)傳遞到 HIDL 中以進(jìn)行傳輸曾雕,還是從 HIDL 接收數(shù)據(jù)奴烙,都不會(huì)改變數(shù)據(jù)的所有權(quán),也就是說(shuō)翻默,數(shù)據(jù)所有權(quán)始終屬于調(diào)用函數(shù)缸沃。數(shù)據(jù)僅需要在函數(shù)被調(diào)用期間保留,可在被調(diào)用的函數(shù)返回?cái)?shù)據(jù)后立即清除修械。

HIDL的架構(gòu)模式

image.png
  • Passthrough 模式
  • Binder 化的 Passthrough HALs
什么是Binder化?

一直以來(lái)检盼,供應(yīng)商進(jìn)程都使用 Binder 進(jìn)程間通信 (IPC) 技術(shù)進(jìn)行通信肯污。在 Android O 中,/dev/binder 設(shè)備節(jié)點(diǎn)成為了框架進(jìn)程的專屬節(jié)點(diǎn)吨枉,這意味著供應(yīng)商進(jìn)程將無(wú)法再訪問(wèn)該節(jié)點(diǎn)蹦渣。供應(yīng)商進(jìn)程可以訪問(wèn) /dev/hwbinder,但必須將其 AIDL 接口轉(zhuǎn)為使用 HIDL貌亭。

HIDL 語(yǔ)法

根據(jù)設(shè)計(jì)柬唯,HIDL 語(yǔ)言與 C 語(yǔ)言類似(但前者不使用 C 預(yù)處理器)。下面未描述的所有標(biāo)點(diǎn)符號(hào)(用途明顯的 = 和 | 除外)都是語(yǔ)法的一部分圃庭。

  • /** */ 表示文檔注釋锄奢。此樣式只能應(yīng)用于類型、方法剧腻、字段和枚舉值聲明拘央。
  • /* */ 表示多行注釋。
  • // 表示注釋一直持續(xù)到行結(jié)束书在。除了 //灰伟,換行符與任何其他空白一樣。
  • 在以下示例語(yǔ)法中儒旬,從 // 到行結(jié)束的文本不是語(yǔ)法的一部分栏账,而是對(duì)語(yǔ)法的注釋。
  • [empty] 表示該字詞可能為空栈源。
  • ? 跟在文本或字詞后挡爵,表示它是可選的。
  • ... 表示包含零個(gè)或多個(gè)項(xiàng)凉翻、用指定的分隔符號(hào)分隔的序列了讨。HIDL 中不含可變參數(shù)捻激。
  • 逗號(hào)用于分隔序列元素。
  • 分號(hào)用于終止各個(gè)元素前计,包括最后的元素胞谭。
  • 大寫字母是非終止符。
  • italics 是一個(gè)令牌系列男杈,例如 *integer**identifier*(標(biāo)準(zhǔn) C 解析規(guī)則)丈屹。
  • constexpr 是 C 樣式的常量表達(dá)式(如 1 + 11L << 3)。
  • import_name 是軟件包或接口名稱伶棒,HIDL 版本編號(hào)中所述的方式加以限定旺垒。
  • 小寫 words 是文本令牌。

實(shí)例:

ROOT =
    PACKAGE IMPORTS PREAMBLE { ITEM ITEM ... }  // not for types.hal
    PREAMBLE = interface identifier EXTENDS
  | PACKAGE IMPORTS ITEM ITEM...  // only for types.hal; no method definitions

ITEM =
    ANNOTATIONS? oneway? identifier(FIELD, FIELD ...) GENERATES?;
  |  struct identifier { SFIELD; SFIELD; ...};  // Note - no forward declarations
  |  union identifier { UFIELD; UFIELD; ...};
  |  enum identifier: TYPE { ENUM_ENTRY, ENUM_ENTRY ... }; // TYPE = enum or scalar
  |  typedef TYPE identifier;

VERSION = integer.integer;

PACKAGE = package android.hardware.identifier[.identifier[...]]@VERSION;

PREAMBLE = interface identifier EXTENDS

EXTENDS = <empty> | extends import_name  // must be interface, not package

GENERATES = generates (FIELD, FIELD ...)

// allows the Binder interface to be used as a type
// (similar to typedef'ing the final identifier)
IMPORTS =
   [empty]
  |  IMPORTS import import_name;

TYPE =
  uint8_t | int8_t | uint16_t | int16_t | uint32_t | int32_t | uint64_t | int64_t |
 float | double | bool | string
|  identifier  // must be defined as a typedef, struct, union, enum or import
               // including those defined later in the file
|  memory
|  pointer
|  vec<TYPE>
|  bitfield<TYPE>  // TYPE is user-defined enum
|  fmq_sync<TYPE>
|  fmq_unsync<TYPE>
|  TYPE[SIZE]

FIELD =
   TYPE identifier

UFIELD =
   TYPE identifier
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SFIELD =
   TYPE identifier
  |  struct identifier { FIELD; FIELD; ...};
  |  union identifier { FIELD; FIELD; ...};
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SIZE =  // Must be greater than zero
     constexpr

ANNOTATIONS =
     [empty]
  |  ANNOTATIONS ANNOTATION

ANNOTATION =
  |  @identifier
  |  @identifier(VALUE)
  |  @identifier(ANNO_ENTRY, ANNO_ENTRY  ...)

ANNO_ENTRY =
     identifier=VALUE

VALUE =
     "any text including \" and other escapes"
  |  constexpr
  |  {VALUE, VALUE ...}  // only in annotations

ENUM_ENTRY =
     identifier
  |  identifier = constexpr

接口描述

HIDL 是圍繞接口進(jìn)行編譯的肤无,接口是面向?qū)ο蟮恼Z(yǔ)言使用的一種用來(lái)定義行為的抽象類型先蒋。每個(gè)接口都是軟件包的一部分。

軟件包

軟件包名稱可以具有子級(jí)宛渐,例如 package.subpackage竞漾。
已發(fā)布的 HIDL 軟件包的根目錄是 hardware/interfaces 或 vendor/vendorName(例如 Pixel 設(shè)備為 vendor/google)。
軟件包名稱在根目錄下形成一個(gè)或多個(gè)子目錄窥翩;定義軟件包的所有文件都位于同一目錄下业岁。
例:
package android.hardware.example.extension.light@2.0
可以在
hardware/interfaces/example/extension/light/2.0
下找到。

軟件包目錄中包含擴(kuò)展名為 .hal 的文件寇蚊。
每個(gè)文件均必須包含一個(gè)指定文件所屬的軟件包和版本的 package 語(yǔ)句笔时。

文件 types.hal(如果存在)并不定義接口,而是定義軟件包中每個(gè)接口可以訪問(wèn)的數(shù)據(jù)類型仗岸。

接口定義

除了 types.hal 之外允耿,其他 .hal 文件均定義一個(gè)接口。
接口通常定義如下:

interface IBar extends IFoo { // IFoo is another interface
    // embedded types
    struct MyStruct {/*...*/};

    // interface methods
    create(int32_t id) generates (MyStruct s);
    close();
};

不含顯式 extends 聲明的接口會(huì)從 android.hidl.base@1.0::IBase(類似于 Java 中的 java.lang.Object)隱式擴(kuò)展爹梁。

導(dǎo)入

import 語(yǔ)句是用于訪問(wèn)其他軟件包中的軟件包接口和類型的 HIDL 機(jī)制右犹。
import 語(yǔ)句本身涉及兩個(gè)實(shí)體:

導(dǎo)入實(shí)體:可以是軟件包或接口;
被導(dǎo)入實(shí)體:也可以是軟件包或接口姚垃。

導(dǎo)入實(shí)體由 import 語(yǔ)句的位置決定念链。
當(dāng)該語(yǔ)句位于軟件包的 types.hal 中時(shí),導(dǎo)入的內(nèi)容對(duì)整個(gè)軟件包是可見的积糯;這是軟件包級(jí)導(dǎo)入掂墓。
當(dāng)該語(yǔ)句位于接口文件中時(shí),導(dǎo)入實(shí)體是接口本身看成;這是接口級(jí)導(dǎo)入君编。

被導(dǎo)入實(shí)體由 import 關(guān)鍵字后面的值決定。
該值不必是完全限定名稱川慌;如果某個(gè)組成部分被刪除了吃嘿,系統(tǒng)會(huì)自動(dòng)使用當(dāng)前軟件包中的信息填充該組成部分祠乃。
對(duì)于完全限定值,支持的導(dǎo)入情形有以下幾種:

  • 完整軟件包導(dǎo)入
    如果該值是一個(gè)軟件包名稱和版本(語(yǔ)法見下文)兑燥,則系統(tǒng)會(huì)將整個(gè)軟件包導(dǎo)入至導(dǎo)入實(shí)體
import android.hardware.nfc@1.0;            // import a whole package
  • 部分導(dǎo)入
    如果值為:
    1.一個(gè)接口亮瓷,則系統(tǒng)會(huì)將該軟件包的 types.hal 和該接口導(dǎo)入至導(dǎo)入實(shí)體中。
    2.在 types.hal 中定義的 UDT降瞳,則系統(tǒng)僅會(huì)將該 UDT 導(dǎo)入至導(dǎo)入實(shí)體中(不導(dǎo)入 types.hal 中的其他類型)嘱支。
import android.hardware.example@1.0::IQuux; 
// import an interface and types.hal
  • 僅類型導(dǎo)入
    如果該值將上文所述的“部分導(dǎo)入”的語(yǔ)法與關(guān)鍵字 types 而不是接口名稱配合使用,則系統(tǒng)僅會(huì)導(dǎo)入指定軟件包的 types.hal 中的 UDT挣饥。
import android.hardware.example@1.0::types; // import just types.hal

接口繼承

接口可以是之前定義的接口的擴(kuò)展除师。
擴(kuò)展可以是以下三種類型中的一種:

1.接口可以向其他接口添加功能,并按原樣納入其 API扔枫。
2.軟件包可以向其他軟件包添加功能汛聚,并按原樣納入其 API。
3.接口可以從軟件包或特定接口導(dǎo)入類型茧吊。

接口只能擴(kuò)展一個(gè)其他接口(不支持多重繼承)贞岭。

接口哈希

哈希是一種旨在防止意外更改接口并確保接口更改經(jīng)過(guò)全面審查的機(jī)制。這種機(jī)制是必需的搓侄,因?yàn)?HIDL 接口帶有版本編號(hào),也就是說(shuō)话速,接口一經(jīng)發(fā)布便不得再更改讶踪,但不會(huì)影響應(yīng)用二進(jìn)制接口 (ABI) 的情況(例如更正備注)除外。

布局

每個(gè)軟件包根目錄(即映射到 hardware/interfaces 的 android.hardware 或映射到 vendor/foo/hardware/interfaces 的 vendor.foo)都必須包含一個(gè)列出所有已發(fā)布 HIDL 接口文件的 current.txt 文件泊交。

# current.txt files support comments starting with a ‘#' character
# this file, for instance, would be vendor/foo/hardware/interfaces/current.txt

# Each line has a SHA-256 hash followed by the name of an interface.
# They have been shortened in this doc for brevity but they are
# 64 characters in length in an actual current.txt file.
d4ed2f0e...995f9ec4 vendor.awesome.foo@1.0::IFoo # comments can also go here

# types.hal files are also noted in types.hal files
c84da9f5...f8ea2648 vendor.awesome.foo@1.0::types

# Multiple hashes can be in the file for the same interface. This can be used
# to note how ABI sustaining changes were made to the interface.
# For instance, here is another hash for IFoo:

# Fixes type where "FooCallback" was misspelled in comment on "FooStruct"
822998d7...74d63b8c vendor.awesome.foo@1.0::IFoo

使用 hidl-gen 添加哈希

什么是hidl-gen

hidl-gen是安卓架構(gòu)HIDL編譯工具乳讥。

可以手動(dòng)將哈希添加到 current.txt 文件中,也可以使用 hidl-gen 添加廓俭。以下代碼段提供了可與 hidl-gen 搭配使用來(lái)管理 current.txt 文件的命令示例(哈希已縮短):

$ hidl-gen -L hash -r vendor.awesome:vendor/awesome/hardware/interfaces -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport vendor.awesome.nfc@1.0::types
9626fd18...f9d298a6 vendor.awesome.nfc@1.0::types
$ hidl-gen -L hash -r vendor.awesome:vendor/awesome/hardware/interfaces -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport vendor.awesome.nfc@1.0::INfc
07ac2dc9...11e3cf57 vendor.awesome.nfc@1.0::INfc
$ hidl-gen -L hash -r vendor.awesome:vendor/awesome/hardware/interfaces -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport vendor.awesome.nfc@1.0
9626fd18...f9d298a6 vendor.awesome.nfc@1.0::types
07ac2dc9...11e3cf57 vendor.awesome.nfc@1.0::INfc
f2fe5442...72655de6 vendor.awesome.nfc@1.0::INfcClientCallback
$ hidl-gen -L hash -r vendor.awesome:vendor/awesome/hardware/interfaces -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport vendor.awesome.nfc@1.0 >> vendor/awesome/hardware/interfaces/current.txt

idl-gen 生成的每個(gè)接口定義庫(kù)都包含哈希云石,通過(guò)調(diào)用 IBase::getHashChain 可檢索這些哈希。

Services & Data Transfer

注冊(cè)Services

HIDL 接口服務(wù)器(實(shí)現(xiàn)接口的對(duì)象)可注冊(cè)為已命名的服務(wù)研乒。
注冊(cè)的名稱不需要與接口或軟件包名稱相關(guān)汹忠。如果沒(méi)有指定名稱,則使用名稱“默認(rèn)”雹熬;這應(yīng)該用于不需要注冊(cè)同一接口的兩個(gè)實(shí)現(xiàn)的 HAL宽菜。

例如,在每個(gè)接口中定義的服務(wù)注冊(cè)的 C++ 調(diào)用是:

status_t status = myFoo->registerAsService();
status_t anotherStatus = anotherFoo->registerAsService("another_foo_service");  // if needed

HIDL 接口的版本包含在接口本身中竿报。
版本自動(dòng)與Service注冊(cè)關(guān)聯(lián)铅乡,并可通過(guò)每個(gè) HIDL 接口上的方法調(diào)用 (android::hardware::IInterface::getInterfaceVersion()) 進(jìn)行檢索。
服務(wù)器對(duì)象不需要注冊(cè)烈菌,并可通過(guò) HIDL 方法參數(shù)傳遞到其他進(jìn)程阵幸,相應(yīng)的接收進(jìn)程會(huì)向服務(wù)器發(fā)送 HIDL 方法調(diào)用花履。

發(fā)現(xiàn)Service

客戶端代碼按名稱和版本請(qǐng)求指定的接口,并對(duì)所需的 HAL 類調(diào)用 getService:

sp<V1_1::IFooService> service = V1_1::IFooService::getService();
sp<V1_1::IFooService> alternateService = V1_1::IFooService::getService("another_foo_service");

Service終止通知

想要在Service終止時(shí)收到通知的客戶端會(huì)接收到框架傳送的終止通知挚赊。
要接收通知诡壁,客戶端必須:

1.將 HIDL 類/接口 hidl_death_recipient(位于 C++ 代碼中,而非 HIDL 中)歸入子類咬腕。
2.替換其 serviceDied() 方法筛峭。
3.實(shí)例化 hidl_death_recipient 子類的對(duì)象尝胆。
4.在要監(jiān)控的服務(wù)上調(diào)用 linkToDeath() 方法,并傳入 IDeathRecipient 的接口對(duì)象。請(qǐng)注意嘀粱,此方法并不具備在其上調(diào)用它的終止接收方或代理的所有權(quán)。

偽代碼示例:

class IMyDeathReceiver : hidl_death_recipient {
  virtual void serviceDied(uint64_t cookie,
                           wp<IBase>& service) override {
    log("RIP service %d!", cookie);  // Cookie should be 42
  }
};
....
IMyDeathReceiver deathReceiver = new IMyDeathReceiver();
m_importantService->linkToDeath(deathReceiver, 42);

PS:

東西很多啊约谈,吐血三升指巡,今天就到這里』鸨牵回去吃大餐室囊。O(∩_∩)O

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市魁索,隨后出現(xiàn)的幾起案子融撞,更是在濱河造成了極大的恐慌,老刑警劉巖粗蔚,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尝偎,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡鹏控,警方通過(guò)查閱死者的電腦和手機(jī)致扯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)当辐,“玉大人抖僵,你說(shuō)我怎么就攤上這事≡稻荆” “怎么了耍群?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)寺晌。 經(jīng)常有香客問(wèn)我世吨,道長(zhǎng),這世上最難降的妖魔是什么呻征? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任耘婚,我火速辦了婚禮,結(jié)果婚禮上陆赋,老公的妹妹穿的比我還像新娘沐祷。我一直安慰自己嚷闭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布赖临。 她就那樣靜靜地躺著胞锰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪兢榨。 梳的紋絲不亂的頭發(fā)上嗅榕,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天,我揣著相機(jī)與錄音吵聪,去河邊找鬼凌那。 笑死,一個(gè)胖子當(dāng)著我的面吹牛吟逝,可吹牛的內(nèi)容都是我干的帽蝶。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼块攒,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼励稳!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起囱井,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤驹尼,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后庞呕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扶欣,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年千扶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骆捧。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡澎羞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出敛苇,到底是詐尸還是另有隱情妆绞,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布枫攀,位于F島的核電站括饶,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏来涨。R本人自食惡果不足惜图焰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蹦掐。 院中可真熱鬧技羔,春花似錦僵闯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至拙绊,卻和暖如春向图,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背标沪。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工榄攀, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谨娜。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓航攒,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親趴梢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子漠畜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容