Android 12系統源碼_AMS(一)Activity啟動流程

前言

Android10之前,在系統剛剛啟動之后,SystemServer進程的startBootstrapServices方法會啟動系統引導服務,像我們常接觸的ActivityManagerService、PowerManagerService、PackageManagerService等都是在這里啟動的,早期Activity的startActivity方法都是通過Instrumentation和ActivityManagerService做交互,但是隨著AMS的職責越來越多、代碼越來越龐大,在Android10以后,Google又對AMS做了進一步拆分,最終拆出來一個新的對象ActivityTaskManagerService,用來管理 Activity及其容器類,比如 Task、Stack、Display 等,以分擔AMS的部分職責。

一、Activity觸發ATMS執行startActivity方法的過程

1、時序圖


image.png

2、Activity的startActivity方法如下所示:

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

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback,
        AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {

    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }
    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        ...代碼省略...       
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

startActivity方法會繼續調用startActivity(Intent intent, Bundle options),最終會繼續調用startActivityForResult方法。

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, null);
    }
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,@Nullable Bundle options) {
              ...代碼省略...
              Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            ...代碼省略...
    }

startActivityForResult方法會調用Instrumentation的execStartActivity方法。

3、Instrumentation 負責調用 Activity 和 Application 的生命周期,每個 Activity 都持有 Instrumentation 對象的一個引用,但是整個進程只會存在一個 Instrumentation 對象,Instrumentation的execStartActivity方法如下所示:

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

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        ...代碼省略...
        try {
            intent.migrateExtraStreamToClipData(who);
            intent.prepareToLeaveProcess(who);
            // 獲取 ActivityTaskManagerService 的代理對象
            int result = ActivityTaskManager.getService().startActivity(whoThread,
                    who.getOpPackageName(), who.getAttributionTag(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()), token,
                    target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

Instrumentation的execStartActivity方法會調用 ActivityTaskManager的getService方法會返回一個IActivityTaskManager類型的實例對象并調用該對象的startActivity方法。

4、在Android12源碼中并不存在IActivityTaskManager.java這樣一個文件,只能找到 IActivityTaskManager.aidl文件:

frameworks/base/core/java/android/app/IActivityTaskManager.aidl

interface IActivityManager {
    int startActivity(in IApplicationThread caller, in String callingPackage,
            in String callingFeatureId, in Intent intent, in String resolvedType,
            in IBinder resultTo, in String resultWho, int requestCode,
            int flags, in ProfilerInfo profilerInfo, in Bundle options);
}

我們知道源碼編譯的時候會將aidl文件轉化為 java 文件,IActivityTaskManager的startActivity方法的調用最終是通過binder來實現跨進程通信的。而IActivityTaskManager.aidl中startActivity方法的具體實現類,其實是ActivityTaskManagerService。

5、ActivityTaskManagerService的startActivity方法如下所示:

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

public class ActivityTaskManagerService extends IActivityTaskManager.Stub {

    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

}

二、ATMS向AMS 發送創建應用進程的過程

1、時序圖和Activity任務棧

image.png

2、ActivityTaskManagerService的startActivity方法會進一步調用startActivityAsUser方法:

public class ActivityTaskManagerService extends IActivityTaskManager.Stub {

    private ActivityStartController mActivityStartController;

    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

    @Override
    public int startActivityAsUser(IApplicationThread caller, String callingPackage,
            String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
            Bundle bOptions, int userId) {
        return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
                true /*validateIncomingUser*/);
    }

    private int startActivityAsUser(IApplicationThread caller, String callingPackage,
            @Nullable String callingFeatureId, Intent intent, String resolvedType,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
        // 檢查調用者的進程是否隔離,如果 isIsolated 則拋出 SecurityException 異常
        assertPackageMatchesCallingUid(callingPackage);
        // 檢查調用者權限,ATMS 根據傳入的 UserId 來確定調用者的權限
        enforceNotIsolatedCaller("startActivityAsUser");

        userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

        return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setCallingFeatureId(callingFeatureId)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setUserId(userId)
                .execute();
    }

    ActivityStartController getActivityStartController() {
        return mActivityStartController;
    }
}

3、startActivityAsUser方法最終會調用ActivityStartController的obtainStarter方法獲取ActivityStarter對象實例:

frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java

public class ActivityStartController {
    ActivityStarter obtainStarter(Intent intent, String reason) {
        return mFactory.obtain().setIntent(intent).setReason(reason);
    }
}

4、獲取ActivityStarter對象之后會調用該對象的的setCaller、setCallingPackage等一系列方法進行參數設置,最后調用execute方法,相關方法的代碼如下所示:

class ActivityStarter {
    //內部靜態類
    static class Request {

        private static final int DEFAULT_CALLING_UID = -1;
        private static final int DEFAULT_CALLING_PID = 0;
        static final int DEFAULT_REAL_CALLING_UID = -1;
        static final int DEFAULT_REAL_CALLING_PID = 0;

        IApplicationThread caller;
        Intent intent;
        NeededUriGrants intentGrants;
        // A copy of the original requested intent, in case for ephemeral app launch.
        Intent ephemeralIntent;
        String resolvedType;
        ActivityInfo activityInfo;
        ResolveInfo resolveInfo;
        IVoiceInteractionSession voiceSession;
        IVoiceInteractor voiceInteractor;
        IBinder resultTo;
        String resultWho;
        int requestCode;
        int callingPid = DEFAULT_CALLING_PID;
        int callingUid = DEFAULT_CALLING_UID;
        String callingPackage;
        @Nullable String callingFeatureId;
        int realCallingPid = DEFAULT_REAL_CALLING_PID;
        int realCallingUid = DEFAULT_REAL_CALLING_UID;
        int startFlags;
        SafeActivityOptions activityOptions;
        boolean ignoreTargetSecurity;
        boolean componentSpecified;
        boolean avoidMoveToFront;
        ActivityRecord[] outActivity;
        Task inTask;
        TaskFragment inTaskFragment;
        String reason;
        ProfilerInfo profilerInfo;
        Configuration globalConfig;
        int userId;
        WaitResult waitResult;
        int filterCallingUid;
        PendingIntentRecord originatingPendingIntent;
        boolean allowBackgroundActivityStart;

        boolean allowPendingRemoteAnimationRegistryLookup;

        Request() {
            reset();
        }
        //為內部設置各種初始化參數
        void reset() {
            caller = null;
            intent = null;
            ...代碼省略...
        }
        //更新參數
        void set(@NonNull Request request) {
            caller = request.caller;
            intent = request.intent;
            ...代碼省略...
        }
  }

    private final RootWindowContainer mRootWindowContainer;
    Request mRequest = new Request();

    ActivityStarter setCaller(IApplicationThread caller) {
        mRequest.caller = caller;
        return this;
    }

     ActivityStarter setCallingPackage(String callingPackage) {
        mRequest.callingPackage = callingPackage;
        return this;
    }

    int execute() {
        try {
              ...代碼省略...
              final Task rootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
              if (rootTask != null) {
                  rootTask.mConfigWillChange = globalConfigWillChange;
              }
              ...代碼省略...
              res = executeRequest(mRequest);  //執行請求操作
              ...代碼省略...
        } finally {
            onExecutionComplete();
        }
    }

}

這里省略了execute的大部分代碼,只保留了關鍵的一步,調用executeRequest方法:

 private int executeRequest(Request request) {
        ...代碼省略...
        final ActivityRecord r = new ActivityRecord.Builder(mService)
                .setCaller(callerApp)
                .setLaunchedFromPid(callingPid)
                .setLaunchedFromUid(callingUid)
                .setLaunchedFromPackage(callingPackage)
                .setLaunchedFromFeature(callingFeatureId)
                .setIntent(intent)
                .setResolvedType(resolvedType)
                .setActivityInfo(aInfo)
                .setConfiguration(mService.getGlobalConfiguration())
                .setResultTo(resultRecord)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setComponentSpecified(request.componentSpecified)
                .setRootVoiceInteraction(voiceSession != null)
                .setActivityOptions(checkedOptions)
                .setSourceRecord(sourceRecord)
                .build();

        ...代碼省略...

        mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
                request.voiceInteractor, startFlags, true /* doResume */, checkedOptions,
                inTask, inTaskFragment, restrictedBgActivity, intentGrants);

        if (request.outActivity != null) {
            request.outActivity[0] = mLastStartActivityRecord;
        }

        return mLastStartActivityResult;
    }

executeRequest方法會先將上面獲取的相關參數封裝成ActivityRecord對象,該對象內部記錄了Activity的所有信息,然后會調用startActivityUnchecked方法:

    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, Task inTask,
            TaskFragment inTaskFragment, boolean restrictedBgActivity,
            NeededUriGrants intentGrants) {
        ...代碼省略...
        try {
            mService.deferWindowLayout();
            Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
            result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, inTaskFragment, restrictedBgActivity,
                    intentGrants);
            ...代碼省略...
        } finally {
              ...代碼省略...
            }
        }
        postStartActivityProcessing(r, result, startedActivityRootTask);
        return result;
    }

startActivityUnchecked方法會進一步調用startActivityInner方法:

    int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, Task inTask,
            TaskFragment inTaskFragment, boolean restrictedBgActivity,
            NeededUriGrants intentGrants) {
        ...代碼省略...
       // 因為可能會復用已經存在的頁面棧而導致棧順序發生變化,這里要獲取頂部的頁面棧
        final Task prevTopTask = mPreferredTaskDisplayArea.getFocusedRootTask();
        final Task reusedTask = getReusableTask();
        ...代碼省略...

        if (mDoResume) {
            final ActivityRecord topTaskActivity = startedTask.topRunningActivityLocked();
            if (!mTargetRootTask.isTopActivityFocusable()
                    || (topTaskActivity != null && topTaskActivity.isTaskOverlay()
                    && mStartActivity != topTaskActivity)) {
                mTargetRootTask.ensureActivitiesVisible(null /* starting */,
                        0 /* configChanges */, !PRESERVE_WINDOWS);
                mTargetRootTask.mDisplayContent.executeAppTransition();
            } else {
                if (mTargetRootTask.isTopActivityFocusable()
                        && !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {
                    mTargetRootTask.moveToFront("startActivityInner");
                }
                //調用RootWindowContainer的resumeFocusedTasksTopActivities方法
                mRootWindowContainer.resumeFocusedTasksTopActivities(
                        mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);
            }
        }
        mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);
        // Update the recent tasks list immediately when the activity starts
        mSupervisor.mRecentTasks.add(startedTask);
        mSupervisor.handleNonResizableTaskIfNeeded(startedTask,
                mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetRootTask);

        return START_SUCCESS;
    }

主要就是處理 Activity 的啟動模式有關的邏輯,處理已經存在的任務棧,最后會調用RootWindowContainer的resumeFocusedTasksTopActivities方法。

5、RootWindowContainer是窗口容器(WindowContainer)的根容器,管理所有的窗口容器,設備上所有的窗口(Window)、顯示屏幕(Display)都是由它來管理的。RootWindowContainer的resumeFocusedTasksTopActivities方法如下所示:

frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

class RootWindowContainer extends WindowContainer<DisplayContent>
        implements DisplayManager.DisplayListener {
    boolean resumeFocusedTasksTopActivities(
            Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
            boolean deferPause) {
        ...代碼省略...
        boolean result = false;
        if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
                || getTopDisplayFocusedRootTask() == targetRootTask)) {
            result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,
                    deferPause);
        }
        for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
            final DisplayContent display = getChildAt(displayNdx);
            final boolean curResult = result;
            boolean[] resumedOnDisplay = new boolean[1];
            display.forAllRootTasks(rootTask -> {
                final ActivityRecord topRunningActivity = rootTask.topRunningActivity();
                if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) {
                    return;
                }
                if (rootTask == targetRootTask) {
                    // Simply update the result for targetRootTask because the targetRootTask
                    // had already resumed in above. We don't want to resume it again,
                    // especially in some cases, it would cause a second launch failure
                    // if app process was dead.
                    resumedOnDisplay[0] |= curResult;
                    return;
                }
                if (rootTask.getDisplayArea().isTopRootTask(rootTask)
                        && topRunningActivity.isState(RESUMED)) {
                    // Kick off any lingering app transitions form the MoveTaskToFront
                    // operation, but only consider the top task and root-task on that
                    // display.
                    rootTask.executeAppTransition(targetOptions);
                } else {
                    resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target);
                }
            });
            result |= resumedOnDisplay[0];
            if (!resumedOnDisplay[0]) {
                //獲取當前屏幕設備的焦點任務棧
                final Task focusedRoot = display.getFocusedRootTask();
                if (focusedRoot != null) {
                    //如果焦點任務棧不為空則喚醒頂部的Activity
                    result |= focusedRoot.resumeTopActivityUncheckedLocked(target, targetOptions);
                } else if (targetRootTask == null) {
                    //否則喚醒首頁Activity
                    result |= resumeHomeActivity(null /* prev */, "no-focusable-task",
                            display.getDefaultTaskDisplayArea());
                }
            }
        }
        return result;
    }
}

resumeFocusedTasksTopActivities方法會恢復對應任務棧頂部的 Activity,如果沒有合法的Activity則恢復首頁Activity,如果有合法的Activity,則調用Task對象的resumeTopActivityUncheckedLocked方法來繼續啟動流程。

6、Task用來描述一個Activity任務棧,Task的resumeTopActivityUncheckedLocked方法如下所示:

frameworks/base/services/core/java/com/android/server/wm/Task.java

class Task extends TaskFragment {

   boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        return resumeTopActivityUncheckedLocked(prev, options, false /* skipPause */);
    }
}

resumeTopActivityUncheckedLocked內部直接調用了同名但參數不同的另一個方法:

    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options, boolean deferPause) {
        if (mInResumeTopActivity) {
            return false;
        }
        boolean someActivityResumed = false;
        try {
            mInResumeTopActivity = true;
            if (isLeafTask()) {
                if (isFocusableAndVisible()) {
                    //繼續調用resumeTopActivityInnerLocked方法
                    someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);
                }
            } else {
                int idx = mChildren.size() - 1;
                while (idx >= 0) {
                    final Task child = (Task) getChildAt(idx--);
                    if (!child.isTopActivityFocusable()) {
                        continue;
                    }
                    if (child.getVisibility(null /* starting */)
                            != TASK_FRAGMENT_VISIBILITY_VISIBLE) {
                        break;
                    }
                    someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options, deferPause);
                    if (idx >= mChildren.size()) {
                        idx = mChildren.size() - 1;
                    }
                }
            }
            final ActivityRecord next = topRunningActivity(true /* focusableOnly */);
            if (next == null || !next.canTurnScreenOn()) {
                checkReadyForSleep();
            }
        } finally {
            mInResumeTopActivity = false;
        }

        return someActivityResumed;
    }

該方法內部會進行一系列條件判斷,最終會繼續調用resumeTopActivityInnerLocked方法:

    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
        if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
            // Not ready yet!
            return false;
        }
        //獲取當前頂部正在運行的Activity
        final ActivityRecord topActivity = topRunningActivity(true /* focusableOnly */);
        if (topActivity == null) {
            // There are no activities left in this task, let's look somewhere else.
            //如果根任務棧為空則返回下一個焦點Activity
            return resumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options);
        }

        final boolean[] resumed = new boolean[1];
        //獲取當前頂部正在運行的Activity的TaskFragment
        final TaskFragment topFragment = topActivity.getTaskFragment();
        //喚醒
        resumed[0] = topFragment.resumeTopActivity(prev, options, deferPause);
        forAllLeafTaskFragments(f -> {
            if (topFragment == f) {
                return;
            }
            if (!f.canBeResumed(null /* starting */)) {
                return;
            }
            resumed[0] |= f.resumeTopActivity(prev, options, deferPause);
        }, true);
        return resumed[0];
    }

resumeTopActivityInnerLocked會調用父類TaskFragment的一個關鍵方法resumeTopActivity來繼續喚醒頂部Activity。

7、TaskFragment的resumeTopActivity方法如下所示:

    final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,
                                    boolean deferPause) {
         ...代碼省略...
        //進程存在
        if (next.attachedToProcess()) {
            ...代碼省略...
            try {
                next.completeResumeLocked();
            } catch (Exception e) {
                ...代碼省略...
            }
        } else {//進程不存在
            ...代碼省略...
            mTaskSupervisor.startSpecificActivity(next, true, true);
        }
        return true;
    }

由于前面已經將對應 Activity 的 ActivityRecord 添加到了棧頂,所以resumeTopActivity方法恢復的就是即將啟動的棧頂 Activity,該方法中做了一系列判斷,確保待啟動 Activity 可見性、預定 Activity 的切換動畫等。然后會判斷將要啟動的Activity進程是否存在,如果存在則會調用ActivityRecord的completeResumeLocked方法:

    void completeResumeLocked() {
        final boolean wasVisible = mVisibleRequested;
        setVisibility(true);
        if (!wasVisible) {
            // Visibility has changed, so take a note of it so we call the TaskStackChangedListener
            mTaskSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
        }
        idle = false;
        results = null;
        if (newIntents != null && newIntents.size() > 0) {
            mLastNewIntent = newIntents.get(newIntents.size() - 1);
        }
        newIntents = null;
        stopped = false;

        if (isActivityTypeHome()) {
            mTaskSupervisor.updateHomeProcess(task.getBottomMostActivity().app);
        }

        if (nowVisible) {
            mTaskSupervisor.stopWaitingForActivityVisible(this);
        }

        // Schedule an idle timeout in case the app doesn't do it for us.
        mTaskSupervisor.scheduleIdleTimeout(this);

        mTaskSupervisor.reportResumedActivityLocked(this);

        resumeKeyDispatchingLocked();
        final Task rootTask = getRootTask();
        mTaskSupervisor.mNoAnimActivities.clear();
        returningOptions = null;

        if (canTurnScreenOn()) {
            mTaskSupervisor.wakeUp("turnScreenOnFlag");
        } else {
            // If the screen is going to turn on because the caller explicitly requested it and
            // the keyguard is not showing don't attempt to sleep. Otherwise the Activity will
            // pause and then resume again later, which will result in a double life-cycle event.
            rootTask.checkReadyForSleep();
        }
    }

則會調用

7、Task是一個管理類,用來管理系統所有Activity,其內部維護了Activity的所有狀態、特殊狀態的Activity以及和Activity相關的列表等數據,Task

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,428評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,024評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,285評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,548評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,328評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,878評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,971評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,098評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,616評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,554評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,725評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,243評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,971評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,361評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,613評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,339評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,695評論 2 370

推薦閱讀更多精彩內容