Android telephony整體結(jié)構(gòu)簡要介紹(RILJ不狮、RILD詳解)

一、前言

本文主要簡要介紹Android整個通信模塊結(jié)構(gòu)信息住拭,并詳細(xì)介紹RIL(modem和上層之間的運(yùn)作方式)。

1.1、基礎(chǔ)概念

1滔岳、通信整體構(gòu)成
首先從硬件層面上來說杠娱,手機(jī)的設(shè)計都是手機(jī)芯片+信號處理模塊,信號處理模塊可以處理modem(調(diào)制解調(diào)器)+RF(射頻)+UICC(通用集成電路卡谱煤,即電話卡) 摊求。

2、AP和BP
其中Android系統(tǒng)刘离、UI和應(yīng)用程序運(yùn)行在手機(jī)芯片上室叉,我們稱之為AP端
手機(jī)視頻通訊控制運(yùn)行在信號處理模塊上的芯片上,我們稱之為BP端
這么設(shè)計核心優(yōu)勢主要是不管操作系統(tǒng)怎么變硫惕,通信模塊都是相同的茧痕。數(shù)據(jù)都不會出錯,增加穩(wěn)定性

1.2恼除、相關(guān)代碼

1踪旷、大部分源碼aosp都有,由于各個廠商定制的不同豁辉,在芯片廠商提供給手機(jī)廠商的原始代碼和aosp的路徑還是有部分差異和定制埃脏。以下代碼路徑以MTK方案舉例。MTK部分型號芯片也在vendor路徑下單獨(dú)提供了實(shí)現(xiàn)的代碼秋忙。但這不影響我們學(xué)習(xí)通信模塊。這部分表格中我就沒有列出來了构舟。
2灰追、本文講解時只列舉核心代碼行,需要讀者自行結(jié)合源碼閱讀

層級 路徑 文件
Apps /packages/apps/Dialer Dialer.apk
/packages/apps/Messaging Messaging.apk
/packages/apps/Contacts Contacts.apk
Providers /packages/providers/TelephonyProvider TelephonyProvider.apk
/packages/providers/ContactsProvider ContactsProvider.apk
Service /packages/services/Telecomm Telecomm.apk
/packages/services/Telephony TeleService.apk
/packages/services/Mms MmsService.apk
vendor/mediatek/proprietary/packages/services/Ims ImsService.apk
Framework frameworks/base/telecomm framework.jar
frameworks/base/telephony framework.jar
frameworks/opt/telephony framework.jar
frameworks/opt/net/ims ims-common.jar
vendor/mediatek/proprietary/frameworks/opt/telecomm mediatek-telephony-common.jar
vendor/mediatek/proprietary/frameworks/opt/telephony mediatek-telephony-common.jar
vendor/mediatek/proprietary/frameworks/opt/telephonybase mediatek-telephony-base.jar
HAL vendor/mediatek/proprietary//hardware/ril/fusion librilfusion.so狗超、libmtk-ril.so弹澎、mtkfusionrild.bin
vendor/mediatek/proprietary/hardware/c2kril/fusion libvia-ril.so
vendor/mediatek/proprietary/hardware/gsm0710muxd gsm0710muxd.bin
vendor/mediatek/proprietary/external/ccci_mdinit_src ccci_mdinit.bin
vendor/mediatek/proprietary/external/ccci_fsd ccci_fsd.bin
Drivers kernel-4.9/drivers/misc/mediatek/eccci kernel img

1.3、軟件架構(gòu)

1努咐、功能說明
由于BP的設(shè)計都是這樣苦蒿,于是不管你是ios還是安卓或是塞班還是老人機(jī),通信模塊提供給我們的功能就這么五個部分:UICC渗稍、ServiceState佩迟、DataConnect、Call竿屹、SMS

功能 簡單介紹
UICC SIM卡:存儲號碼报强、短信、PIN拱燃、PUK秉溉、駐網(wǎng)鑒權(quán)、STK工具包、2G召嘶、3G父晶、4G
ServiceState 網(wǎng)絡(luò)服務(wù):網(wǎng)絡(luò)制式、運(yùn)營商名字弄跌、信號格數(shù)甲喝、時區(qū)、漫游碟绑、注冊情況
DataConnect 上網(wǎng)服務(wù):2G/3G/4G/5G
Call 通話:撥號俺猿、接聽、掛斷格仲、保持押袍、恢復(fù)、多方通話
SMS 短信:普通短信凯肋、長短信

2谊惭、簡單的畫了一張Android通信模塊的架構(gòu)圖,功能設(shè)計完全按照Android分層而來

通信模塊架構(gòu)圖.png

軟件架構(gòu)圖中其他幾個功能點(diǎn)簡單介紹

功能 簡單介紹
應(yīng)用內(nèi) Dialer撥號侮东、Contacts聯(lián)系人圈盔、Mms短信、settings設(shè)置悄雅、browser瀏覽器
TeleService Telephony應(yīng)用框架:數(shù)據(jù)連接驱敲、MMS業(yè)務(wù)邏輯、Call控制宽闲、RILD通信
Telecom 管理通話众眨、和TeleService交互對應(yīng)用層提供接口
通話 GSMCdmaPhone:2G、3G通話 ImsPhone:4G通話(Volte)
RILD RILD是RILJ和Modem中間層:1容诬、RILJ下發(fā)請求->RILD將Request轉(zhuǎn)換為Modem的AT指令發(fā)送2娩梨、Modem上報或者返回的消息->RILD處理傳給RILJ
Gsm0710muxd 1、Gsm0710muxd是AT指令通道進(jìn)行復(fù)用的守護(hù)進(jìn)程2览徒、Gsm0710是開源多路復(fù)用協(xié)議狈定,提高M(jìn)odem和AP間AT指令的通信效率
CCCI_FSD 1、Modem不能直接操作文件系統(tǒng)习蓬、CCCI_FSD是AP提供給Modem文件守護(hù)進(jìn)程2纽什、通過FSDmodem就可以操作文件系統(tǒng)
CCCI_MDINIT Modem狀態(tài)守護(hù)進(jìn)程:啟動、停止躲叼、重啟稿湿、飛行模式、reset重置
ECCCI driver 驅(qū)動框架:復(fù)用不同modem驅(qū)動押赊、減少中斷內(nèi)存開支饺藤、AT指令轉(zhuǎn)換modem數(shù)據(jù)包斑、網(wǎng)卡驅(qū)動、文件系統(tǒng)涕俗、Audio通話數(shù)據(jù)

二罗丰、RIL詳細(xì)介紹

2.1、phone進(jìn)程

packages\services\Telephony
phone進(jìn)程是各個功能詳細(xì)模塊framework開始的地方
1再姑、自啟動

 <application android:name="PhoneApp"
            android:persistent="true"

在elephony#AndroidManifest.xml中有persistent標(biāo)記萌抵。有此標(biāo)記AMS會持續(xù)保證進(jìn)程(com.android.phone)存活,意外掛掉也會自動重啟元镀。所以PhoneApp(telephony的Application)就是最初的代碼入口

public class PhoneApp extends Application {
    public void onCreate() {
        mPhoneGlobals = new PhoneGlobals(this);
        mPhoneGlobals.onCreate();
        mTelephonyGlobals = new TelephonyGlobals(this);
        mTelephonyGlobals.onCreate();

2绍填、PhoneGlobals#onCreate
在PhoneGlobals的構(gòu)造函數(shù)里,開始了Phone對象的創(chuàng)建(makeDefaultPhones).

public void onCreate() {
        PhoneFactory.makeDefaultPhones(this);
    }
public static void makeDefaultPhone(Context context) {
    //有幾張卡創(chuàng)建幾個Phone對象
    sPhones = new Phone[numPhones];
    //創(chuàng)建RILJ對象
    sCommandsInterfaces = new RIL[numPhones];

2.2栖疑、RIL

名字 介紹
RILJ java層讨永,運(yùn)行在telephony的phone進(jìn)程,它為上層提供訪問modem的入口和消息接收
RILD HAL層遇革,系統(tǒng)守護(hù)進(jìn)程卿闹。RILJ和Modem中間層:1、RILJ下發(fā)請求->RILD將Request轉(zhuǎn)換為Modem的AT指令發(fā)送2萝快、Modem上報或者返回的消息->RILD處理傳給RILJ

在Android8.0之前锻霎,RILJ和modem通信時通過socket連接發(fā)送AT指令來進(jìn)行通信。現(xiàn)在的版本已經(jīng)改用HIDL通信的方式揪漩。HIDL和AIDL很類似旋恼。可以簡單的理解為綁定底層的服務(wù)來作用到對應(yīng)的功能上奄容。

2.2.1蚌铜、RILJ

基本代碼結(jié)構(gòu)

public class RIL extends BaseCommands implements CommandsInterface
public abstract class BaseCommands implements CommandsInterface 
public interface CommandsInterface 

這里的RIL類就是我們口中的RILJ,采用依賴倒轉(zhuǎn)原則嫩海,定義功能。
<1>囚痴、 CommandsInterface接口中定義一些常量表示狀態(tài)叁怪,再抽象一些方法。
<2>深滚、抽象類實(shí)現(xiàn)方法奕谭,觀察者模式 register、unregister注冊監(jiān)聽痴荐。留空一些方法具體實(shí)現(xiàn)在RIL類中實(shí)現(xiàn)
<3>血柳、RIL類則是具體的功能實(shí)現(xiàn)。
<4>生兆、在BaseCommands中定義了大量RegistrantList和Registrant對象难捌,這兩個對象是對handler消息的封裝,結(jié)合register注冊的監(jiān)聽,就能把從RILD發(fā)送上來的消息傳遞給監(jiān)聽的對象
<5>根吁、RILJ消息的下發(fā)和接收都是通過HIDL拿到radio service员淫,間接通過hidl service來操作和modem之間消息的上傳和下發(fā)。
獲得radio hidl service
RIL.java中RIL#getRadioProxy

public IRadio getRadioProxy(Message result) {
        ...
        try {
            mRadioProxy = IRadio.getService(HIDL_SERVICE_NAME[mPhoneId == null ? 0 : mPhoneId],true);   // mPhoneId sim卡id击敌,一張卡一個service
             if (mRadioProxy != null) {
                mRadioProxy.linkToDeath(mRadioProxyDeathRecipient,
                        mRadioProxyCookie.incrementAndGet());
                mRadioProxy.setResponseFunctions(mRadioResponse, mRadioIndication);
            } else {
                riljLoge("getRadioProxy: mRadioProxy == null");
            }
        ...
        return mRadioProxy;
    }

下發(fā)

@Override
    public void getIccCardStatus(Message result) {
        IRadio radioProxy = getRadioProxy(result);
        if (radioProxy != null) {
             // 封裝要發(fā)送的數(shù)據(jù)
            RILRequest rr = obtainRequest(RIL_REQUEST_GET_SIM_STATUS, result,
                    mRILDefaultWorkSource);
      
            if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));

            try {
                // 調(diào)用到HIDL 提供的radioservice
                radioProxy.getIccCardStatus(rr.mSerial);
            } catch (RemoteException | RuntimeException e) {
                handleRadioProxyExceptionForRR(rr, "getIccCardStatus", e);
            }
        }
    }

上傳
在獲得hw aodio service的時候介返,setResponseFunctions(mRadioResponse, mRadioIndication)傳入了兩個對象,他們負(fù)責(zé)消息的接收和監(jiān)聽沃斤。
這里隨便復(fù)制了一個狀態(tài)改變的回調(diào):RadioIndication#radioStateChanged

public void radioStateChanged(int indicationType, int radioState) {
        mRil.processIndication(indicationType);

        CommandsInterface.RadioState newState = getRadioStateFromInt(radioState);
        if (RIL.RILJ_LOGD) {
            mRil.unsljLogMore(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, "radioStateChanged: " +
                    newState);
        }

        mRil.setRadioState(newState);
    }

2.2.2 RILD

temp.png

RILD程序架構(gòu)圖清晰的表示了RILD的一個初始化過程圣蝎。歸納為如下四點(diǎn)
1、ril.cpp來統(tǒng)管功能衡瓶,具體實(shí)現(xiàn)在ril_event,reference_ril,atchanel,ril_service里
2徘公、第一個流程:startEventLoop開啟loop循環(huán)
3、第二個流程:rilInit初始化鞍陨,打開AT通道流程
4步淹、第三個流程: 注冊回調(diào)函數(shù),ril管理

2.2.2.1诚撵、loop循環(huán)簡要說明

第一個流程開啟loop循環(huán)后缭裆,按流程圖走到ril_event#ril_event_loop方法,這里和handler原理中l(wèi)oop循環(huán)類似寿烟,無限循環(huán)查找處理三個鏈表中的event澈驼,下面截取最后循環(huán)的代碼和鏈表結(jié)構(gòu)體

static struct ril_event * watch_table[MAX_FD_EVENTS];
static struct ril_event timer_list;
static struct ril_event pending_list;

struct ril_event {
    struct ril_event *next;
    struct ril_event *prev;

    int fd;
    int index;
    bool persist;
    struct timeval timeout;
    ril_event_cb func;
    void *param;
};

void ril_event_loop()
{
    for (;;) {
        // Check for timeouts
        processTimeouts();
        // Check for read-ready
        processReadReadies(&rfds, n);
        // Fire away
        firePending();
    }
}

2.2.2.2、打開AT通道簡要說明

打開AT通道筛武,按代碼流程rilInit走到at_open時缝其,主要執(zhí)行了readerLoop,在readerLoop中徘六,此時AT通道有消息就會被處理内边。分別由s_unsolHandler 處理主動上報的消息(比如有短消息),processLine經(jīng)過上層請求過后的需要回復(fù)到上層的消息待锈,比如請求sim卡信息

static void *readerLoop(void *arg __unused)
{
    for (;;) {
            line1 = strdup(line);
            line2 = readline();
            if (s_unsolHandler != NULL) {
                s_unsolHandler (line1, line2);
            }
        } else {
            processLine(line);
        }
}

s_unsolHandler上報到RILJ

// ril.cpp
void RIL_onUnsolicitedResponse(int unsolResponse, const void *data,
                                size_t datalen) {
    ret = s_unsolResponses[unsolResponseIndex].responseFunction(
            (int) soc_id, responseType, 0, RIL_E_SUCCESS, const_cast<void*>(data),
            datalen);

static UnsolResponseInfo s_unsolResponses[] = {
#include "ril_unsol_commands.h"
};

//ril_unsol_commands.h
    {RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, radio::radioStateChangedInd, WAKE_PARTIAL},
    {RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, radio::callStateChangedInd, WAKE_PARTIAL},
    {RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, radio::networkStateChangedInd, WAKE_PARTIAL},
    ...

// ril_service.cpp
int radio::radioStateChangedInd(int slotId,
        Return<void> retStatus = radioService[slotId]->mRadioIndication->radioStateChanged(
                convertIntToRadioIndicationType(indicationType), radioState);
        radioService[slotId]->checkReturnStatus(retStatus);
    }

    return 0;
}

sp<RadioImpl> radioService[SIM_COUNT];

struct RadioImpl : public V1_1::IRadio {
    int32_t mSlotId;
    sp<IRadioResponse> mRadioResponse;
    sp<IRadioIndication> mRadioIndication;

<1>漠其、處理先也是流程化傳遞,先是ril.cpp的RIL_onUnsolicitedResponse然后通過結(jié)構(gòu)體傳遞到ril_unsol_commands.h里聲明的radio::radioStateChangedInd等方法
<2>竿音、radio::radioStateChangedInd等方法的具體實(shí)現(xiàn)在ril_service.cpp中
<3>和屎、ril_service在實(shí)現(xiàn)的時候,上報就交給了ril_service中RadioImpl結(jié)構(gòu)體里的mRadioResponse和mRadioIndication春瞬。這兩個對象就是2.2.1柴信、RILJ小結(jié)獲得hw radio service的時候傳進(jìn)來的兩個對象。
<4>宽气、總結(jié)一下就是rild初始化打開AT通道后随常,從AT通道中讀到要上報的消息時潜沦,交給mRadioResponse和mRadioIndication來上報。RILJ拿到的hw radio service 就是ril_service
<5>线罕、RadioImpl 這個將在第三部分講止潮,可以簡單理解它為ril_service的代理。
processLine上報
這種上報也有幾種類型

static void processLine(const char *line)
{
 if (sp_response == NULL) {
        /* no command pending */  
        handleUnsolicited(line); //  1钞楼、主動上報
    } else if (isFinalResponseSuccess(line)) {
        sp_response->success = 1;
        handleFinalResponse(line); // 2喇闸、成功,標(biāo)準(zhǔn)響應(yīng)
    } else if (isFinalResponseError(line)) {
        sp_response->success = 0;
        handleFinalResponse(line);  // 3、失敗询件,標(biāo)準(zhǔn)響應(yīng)
    }  else if (s_smsPDU != NULL && 0 == strcmp(line, "> ")) {
        // See eg. TS 27.005 4.3
        // Commands like AT+CMGS have a "> " prompt
        writeCtrlZ(s_smsPDU);   // 4燃乍、收到>符號,發(fā)送sms數(shù)據(jù)再繼續(xù)等待響應(yīng)
        s_smsPDU = NULL;
    }  else switch (s_type) {   // 5宛琅、命令有具體的響應(yīng)信息需要對應(yīng)分析
        // case中省略了處理方法
        case NO_RESULT:
        case NUMERIC:
        case SINGLELINE:
        case MULTILINE:
        break;

// 這里以handleFinalResponse舉例
static void handleFinalResponse(const char *line)
{
    // 把消息返回RILJ
    sp_response->finalResponse = strdup(line);
    //s_commandcond脫離阻塞狀態(tài) 
    pthread_cond_signal(&s_commandcond);
}

static int at_send_command_full_nolock (const char *command, ATCommandType type,
                    const char *responsePrefix, const char *smspdu,
                    long long timeoutMsec, ATResponse **pp_outResponse)
{
    while (sp_response->finalResponse == NULL && s_readerClosed == 0) {
        if (timeoutMsec != 0) {
            err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts);
        } else {
            err = pthread_cond_wait(&s_commandcond, &s_commandmutex);
        }

    if (pp_outResponse == NULL) {
        at_response_free(sp_response);
    } else {
        /* line reader stores intermediate responses in reverse order */
        reverseIntermediates(sp_response);
        *pp_outResponse = sp_response;
    }

int at_send_command (const char *command, ATResponse **pp_outResponse) {
    err = at_send_command_full (command, NO_RESULT, NULL,
                                    NULL, 0, pp_outResponse);
}

//ril_service.cpp
static void onRequest (int request, void *data, size_t datalen, RIL_Token t) {
            err = at_send_command_numeric("AT+CIMI", &p_response);

<1>刻蟹、processLine處理也有5種類型,流程上都類似嘿辟。以handleFinalResponse普通流程舉例
<2>舆瘪、從handleFinalResponse線程鎖跟蹤到at_send_command_full_nolock,線程解鎖被再次喚醒過后把結(jié)果傳給了函數(shù)參數(shù)*pp_outResponse红伦。
<3>再跟蹤at_send_command_full_nolock方法的調(diào)用流程英古,來自at_send_command 方法。而這個pp_outResponse就是這樣傳過來的昙读。
<4>最后截取了ril_service.cpp中一次包含response的請求代碼片段
<5>所以AT請求下發(fā)也是ril_service.cpp中眾多方法間接調(diào)用at_send_command傳遞即可召调。

2.2.2.3、注冊回調(diào)函數(shù)蛮浑,ril管理說明

RIL_register (const RIL_RadioFunctions *callbacks) {
    radio::registerService(&s_callbacks, s_commands);
}
//ril_service.cpp
void radio::registerService(RIL_RadioFunctions *callbacks, CommandInfo *commands) {
    s_vendorFunctions = callbacks;
    s_commands = commands;
    for (int i = 0; i < simCount; i++) {
        radioService[i] = new RadioImpl;
}

<1>唠叛、注冊函數(shù)就簡單了,注冊時把callback傳進(jìn)來還為每一張SIM卡創(chuàng)建了一個RadioImpl對象
<2>沮稚、radioService這里就對RIL進(jìn)行收發(fā)管理艺沼。

2.2.2.4、RILD小結(jié)

<1>蕴掏、RILJ層通過HIDL拿到reference-ril.c提供的radio service障般,通過service來下發(fā)和上傳回調(diào)
<2>ril.cpp通過三大流程調(diào)用,來實(shí)現(xiàn)rild的功能囚似。
<3>radio service下發(fā)是調(diào)用atchannel.c中at_send_command來給modem發(fā)送at指令
<4>radio service上傳是通過set的兩個回調(diào)接口向RILJ傳遞信息∠叩茫或者通過at_send_command傳遞的response回傳消息饶唤。

三、寫在最后

對于Android通信模塊來說贯钩,主要學(xué)習(xí)的是流程跟蹤募狂。從調(diào)用棧來講办素,不管是讀取SIM卡信息or狀態(tài),還是上網(wǎng)祸穷、撥號性穿、發(fā)短信。都是通過RIL層來轉(zhuǎn)發(fā)AT指令雷滚。通過對RIL的了解以達(dá)到了解整個通信模塊咋個工作的目的需曾。如果要具體的去修改或者維護(hù)telephony模塊,還需要對具體功能的流程進(jìn)行分析掌握祈远,才能游刃有余呆万。

read the fucking source code!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市车份,隨后出現(xiàn)的幾起案子谋减,更是在濱河造成了極大的恐慌,老刑警劉巖扫沼,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件出爹,死亡現(xiàn)場離奇詭異,居然都是意外死亡缎除,警方通過查閱死者的電腦和手機(jī)严就,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來伴找,“玉大人盈蛮,你說我怎么就攤上這事〖及” “怎么了抖誉?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長衰倦。 經(jīng)常有香客問我袒炉,道長,這世上最難降的妖魔是什么樊零? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任我磁,我火速辦了婚禮,結(jié)果婚禮上驻襟,老公的妹妹穿的比我還像新娘夺艰。我一直安慰自己,他們只是感情好沉衣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布郁副。 她就那樣靜靜地躺著,像睡著了一般豌习。 火紅的嫁衣襯著肌膚如雪存谎。 梳的紋絲不亂的頭發(fā)上拔疚,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機(jī)與錄音既荚,去河邊找鬼稚失。 笑死,一個胖子當(dāng)著我的面吹牛恰聘,可吹牛的內(nèi)容都是我干的句各。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼憨琳,長吁一口氣:“原來是場噩夢啊……” “哼诫钓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起篙螟,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤菌湃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后遍略,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惧所,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年绪杏,在試婚紗的時候發(fā)現(xiàn)自己被綠了下愈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡蕾久,死狀恐怖势似,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情僧著,我是刑警寧澤履因,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站盹愚,受9級特大地震影響栅迄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜皆怕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一毅舆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧愈腾,春花似錦憋活、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春盐欺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背仅醇。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工冗美, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人析二。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓粉洼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親叶摄。 傳聞我的和親對象是個殘疾皇子属韧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

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