Android PMS 启动流程

一、关键类的介绍

1、核心类介绍

/frameworks/base/core/java/android/app/ApplicationPackageManager.java
/frameworks/base/services/java/com/android/server/SystemServer.java
/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
/frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java
/frameworks/base/services/core/java/com/android/server/pm/PackageDexOptimizer.java
/frameworks/base/services/core/java/com/android/server/pm/Installer.java
/frameworks/base/services/core/java/com/android/server/pm/Settings.java
/frameworks/base/services/core/java/com/android/server/pm/permission/BasePermission.java
/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
/frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
/frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
/frameworks/base/core/java/android/content/pm/IPackageManager.aidl
/frameworks/base/core/java/android/content/pm/PackageManager.java
/frameworks/base/core/java/com/android/server/SystemConfig.java

2、PackageManager

  • 提供一个ApplicationInfo的所有信息

  • 提供权限相关信息

  • 提供一个安装包信息

  • 安装、卸载、更新app功能

3、Installer :对app进行操作

  • 安装

  • 卸载

  • 更新

  • 迁移

3、Settings

  • 创建”data/system”目录
  • 创建一些xml文件

    packages.xml 记录所有安装app的信息,当系统进行程序安装、卸载和更新等操作时,均会更新该文件。
    packages-backup.xml 备份文件
    packages-stopped.xml 记录被用户强行停止的应用的Package信息
    packages-stopped-backup.xml 备份文件
    packages.list 记录非系统自带的APK的数据信息,这些APK有变化时会更新该文件

  • 配置相应的权限
  • readLPw()函数:

从/data/system/packages.xml或packages-backup.xml文件中获得packages、permissions相关信息,添加到相关内存列表中。packages.xml文件记录了系统的permisssions以及每个APK的name、codePath、flags、version等信息这些信息主要通过APK的AndroidManifest.xml解析获取,解析完APK后将更新信息写入这个文件,下次开机直接从里面读取相关信息添加到内存相关结构中。当有APK升级、安装或删除时会更新这个文件。

  • writeLPr函数:

将解析出的每个APK的配置信息(mSetting.mPackages)保存到packages.xml和packages.list文件。packages.list记录了如下数据:pkgName, userId, debugFlag, dataPath(包的数据路径)

4、SystemConfig

通过readPermissions解析指定目录下的xml文件:

  • /system/etc/sysconfig
  • /system/etc/permissions
  • /odm/etc/sysconfig
  • /odm/etc/permissions
  • /oem/etc/sysconfig
  • /oem/etc/permissions

readPermissions函数最终会调用readPermissionsFromXml()使用XMLPullParser的方式解析这些XML文件,然后把解析出来的数据结构保存到PMS中。

5、DefaultPermissionGrantPolicy

默认组件提前授予运行时权限,DefaultPermissionGrantPolicy在PermissionManagerService的构造函数中被创建。

6、PackageInstallerService

管理应用的安装过程。

二、PMS初始化

查看系统网址: http://androidxref.com/9.0.0_r3/

1、启动SystemServer服务

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

 /**
     * The main entry point from zygote.  SystemServer启动入口
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }

    private void run() {
     .........
        // Start services : 分开启动目的:加快手机启动速度
        try {
            //启动AMS、PMS、WMS
            startBootstrapServices();
            //启动核心服务
            startCoreServices();
            //启动三方服务(Launcher启动)
            startOtherServices();
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            traceEnd();
        }
        .........
    }


    private void startBootstrapServices() {
        .......
        /**
         * 以便它有机会创建关键目录,如/data/user具有适当的权限。其他service都会用到此对象
         **/
        traceBeginAndSlog("StartInstaller");  //加系统日志,起始位置
        Installer installer = mSystemServiceManager.startService(Installer.class);
        traceEnd();  // 日志结束
        .......

        // Start the package manager.   启动PMS服务
        if (!mRuntimeRestart) {
            MetricsLogger.histogram(null, "boot_package_manager_init_start",
                    (int) SystemClock.elapsedRealtime());
        }
        traceBeginAndSlog("StartPackageManagerService"); 
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();
        traceEnd();

        ......
    }

2、初始化PMS

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

  • 创建类时候会把Data分区一些目录创建好,比如/data/app。
  • PackageManagerService构造方法
    /**
      加载类之前在Data分区创建一些目录
    **/
    /**
     * Directory where installed applications are stored
     */
    private static final File sAppInstallDir =
            new File(Environment.getDataDirectory(), "app");
    /**
     * Directory where installed application's 32-bit native libraries are copied.
     */
    private static final File sAppLib32InstallDir =
            new File(Environment.getDataDirectory(), "app-lib");
    /**
     * Directory where code and non-resource assets of forward-locked applications are stored
     */
    private static final File sDrmAppPrivateInstallDir =
            new File(Environment.getDataDirectory(), "app-private");

    //PackageManagerService的入口
      public static PackageManagerService main(Context context, Installer installer,
                                             boolean factoryTest, boolean onlyCore) {
        // Self-check for initial settings.
        PackageManagerServiceCompilerMapping.checkProperties();

        PackageManagerService m = new PackageManagerService(context, installer,
                factoryTest, onlyCore);
        m.enableSystemUserPackages();
        ServiceManager.addService("package", m);
        final PackageManagerNative pmn = m.new PackageManagerNative();
        ServiceManager.addService("package_native", pmn);
        return m;
    }

3、PMS构造方法

  • BOOT_PROGRESS_PMS_START : PMS开始扫描安装的应用

UserManagerService :多用户管理服务类。主要功能是创建和删除用户,以及查询用户信息
PermissionManagerService :权限管理类。创建PermissionSettings类,它是记录所有权限相关信息
Settings :保存安装包信息类。主要涉及/data/system/目录的packages.xml(逆向工程常看文件),packages-backup.xml,packages.list,packages-stopped.xml,packages-stopped-backup.xml等文件。
PackageDexOptimizer :创建Dex优化工具类
PackageHandler : APK的复制和安装工作类

        public PackageManagerService(Context context, Installer installer,
                                 // Create sub-components that provide services / data. Order here is important.
                                 synchronized (mInstallLock) {
        //打印开始阶段日志
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
                SystemClock.uptimeMillis())
        ........
        synchronized (mPackages) {
            // Expose private service for system components to use.
            LocalServices.addService(
                    PackageManagerInternal.class, new PackageManagerInternalImpl());
            //UserManagerService的主要功能是创建和删除用户,以及查询用户信息。
            sUserManager = new UserManagerService(context, this,
                    new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
            //PermissionManagerService 权限管理类,创建PermissionSettings类,它是记录所有权限相关信息
            mPermissionManager = PermissionManagerService.create(context,
                    new DefaultPermissionGrantedCallback() {
                        @Override
                        public void onDefaultRuntimePermissionsGranted(int userId) {
                            synchronized (mPackages) {
                                mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
                            }
                        }
                    }, mPackages /*externalLock*/);
            mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();
            //它是Android全局管理者,用于协助PMS保存所有的安装包信息
            mSettings = new Settings(mPermissionManager.getPermissionSettings(), mPackages);
        }
          ........
          //创建Dex优化工具类
          mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
                "*dexopt*");
          // 权限变化监听器
          mOnPermissionChangeListeners = new OnPermissionChangeListeners(FgThread.get().getLooper());
          ........
         //得到全局系统配置信息。
         SystemConfig systemConfig = SystemConfig.getInstance();
         mAvailableFeatures = systemConfig.getAvailableFeatures();
         Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }
        ........
        synchronized (mInstallLock) {
            // writer
            synchronized (mPackages) {
                mHandlerThread = new ServiceThread(TAG,
                        Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
                mHandlerThread.start();
                // PMS通过PackageHandler驱动APK的复制和安装工作
                mHandler = new PackageHandler(mHandlerThread.getLooper());
                mProcessLoggingHandler = new ProcessLoggingHandler();
                //mHandler添加到Watchdog的监测导致系统卡住
                Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
                mInstantAppRegistry = new InstantAppRegistry(this);
                // 通过 systemConfig 获取系统中的共享库列表
                ArrayMap<String, String> libConfig = systemConfig.getSharedLibraries();
                final int builtInLibCount = libConfig.size();
                for (int i = 0; i < builtInLibCount; i++) {
                    String name = libConfig.keyAt(i);
                    String path = libConfig.valueAt(i);
                    //把共享库写入系统路径    L: lock    P: packages一系列xml文件   w: write
                    addSharedLibraryLPw(path, null, name, SharedLibraryInfo.VERSION_UNDEFINED,
                            SharedLibraryInfo.TYPE_BUILTIN, PLATFORM_PACKAGE_NAME, 0);
                }
            }
        }
  • BOOT_PROGRESS_PMS_SYSTEM_SCAN_START :PMS扫描/system目录下的安装包

app : 存放系统App,包括了谷歌内置的App也有厂商或者运营商提供的App
framework : 存放应用框架层的jar包
priv-app: 存放特权App
lib : 存放so文件
fonts: 存放系统字体文件
media: 存放系统的各种声音,比如铃声、提示音,以及系统启动播放的动画
vendor: 它用来存储厂商对Android系统的定制部分。

系统扫描阶段的主要工作有以下3点:

  • 创建/system的子目录,比如/system/framework、/system/priv-app和/system/app等等
  • 扫描系统文件,比如/vendor/overlay、/system/framework、/system/app等等目录下的文件。
  • 对扫描到的系统文件做后续处理。
public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
            ...
            //打印扫描系统阶段日志
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
                    startTime);
            ...
            //在/system中创建framework目录
            File frameworkDir = new File(Environment.getRootDirectory(), "framework");
            ...
            //扫描/vendor/overlay目录下的文件
            scanDirTracedLI(new File(VENDOR_OVERLAY_DIR), mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR
                    | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
            mParallelPackageParserCallback.findStaticOverlayPackages();
            //扫描/system/framework 目录下的文件
            scanDirTracedLI(frameworkDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR
                    | PackageParser.PARSE_IS_PRIVILEGED,
                    scanFlags | SCAN_NO_DEX, 0);
            final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
            //扫描 /system/priv-app 目录下的文件
            scanDirTracedLI(privilegedAppDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR
                    | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
            final File systemAppDir = new File(Environment.getRootDirectory(), "app");
            //扫描/system/app 目录下的文件
            scanDirTracedLI(systemAppDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
            File vendorAppDir = new File("/vendor/app");
            try {
                vendorAppDir = vendorAppDir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
            }
            //扫描 /vendor/app 目录下的文件
            scanDirTracedLI(vendorAppDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

           //扫描/oem/app 目录下的文件
            final File oemAppDir = new File(Environment.getOemDirectory(), "app");
            scanDirTracedLI(oemAppDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

            //这个列表代表有可能有升级包的系统App
            final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();//1
            if (!mOnlyCore) {
                Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
                while (psit.hasNext()) {
                    PackageSetting ps = psit.next();                 
                    if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                        continue;
                    }
                    //这里的mPackages的是PMS的成员变量,代表scanDirTracedLI方法扫描上面那些目录得到的 
                    final PackageParser.Package scannedPkg = mPackages.get(ps.name);
                    if (scannedPkg != null) {           
                        if (mSettings.isDisabledSystemPackageLPr(ps.name)) {//2
                           ...
                            //将这个系统App的PackageSetting从PMS的mPackages中移除
                            removePackageLI(scannedPkg, true);
                            //将升级包的路径添加到mExpectingBetter列表中
                            mExpectingBetter.put(ps.name, ps.codePath);
                        }
                        continue;
                    }
                   
                    if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
                       ...   
                    } else {
                        final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
                        //这个系统App升级包信息在mDisabledSysPackages中,但是没有发现这个升级包存在
                        if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {//5
                            possiblyDeletedUpdatedSystemApps.add(ps.name);//
                        }
                    }
                }
            }
            ...        
}
  • BOOT_PROGRESS_PMS_DATA_SCAN_START:PMS扫描/data目录下的安装包

app: 存储用户自己安装的App
data: 存储所有已安装的App数据的目录,每个App都有自己单独的子目录
app-private: App的私有存储空间
app-lib: 存储所有App的Jni库
system: 存放系统配置文件
anr: 用于存储ANR发生时系统生成的traces.txt文件

扫描Data分区阶段主要做了以下几件事:

  • 扫描/data/app和/data/app-private目录下的文件。
  • 遍历possiblyDeletedUpdatedSystemApps列表,注释1处如果这个系统App的包信息不在PMS的变量mPackages中,说明是残留的App信息,后续会删除它的数据。注释2处如果这个系统App的包信息在mPackages中,说明是存在于Data分区,不属于系统App,那么移除其系统权限。
  • 遍历mExpectingBetter列表,注释3处根据系统App所在的目录设置扫描的解析参数,注释4处的方法内部会将packageName对应的包设置数据(PackageSetting)添加到mSettings的mPackages中。注释5处扫描系统App的升级包,最后清除mExpectingBetter列表。
public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
    ...        
    mSettings.pruneSharedUsersLPw();
    //如果没有加密设备,那么就开始扫描Data分区。
    if (!mOnlyCore) {
        //打印扫描Data分区阶段日志
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                SystemClock.uptimeMillis());
        //扫描/data/app目录下的文件       
        scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
        //扫描/data/app-private目录下的文件   
        scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
                | PackageParser.PARSE_FORWARD_LOCK,
                scanFlags | SCAN_REQUIRE_KNOWN, 0);
        //扫描完Data分区后,处理possiblyDeletedUpdatedSystemApps列表
        for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
            PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
            // 从mSettings.mDisabledSysPackages变量中移除去此应用
            mSettings.removeDisabledSystemPackageLPw(deletedAppName);
            String msg;
          //1:如果这个系统App的包信息不在PMS的变量mPackages中,说明是残留的App信息,后续会删除它的数据。
            if (deletedPkg == null) {
                msg = "Updated system package " + deletedAppName
                        + " no longer exists; it's data will be wiped";
                // Actual deletion of code and data will be handled by later
                // reconciliation step
            } else {
            //2:如果这个系统App在mPackages中,说明是存在于Data分区,不属于系统App,那么移除其系统权限。
                msg = "Updated system app + " + deletedAppName
                        + " no longer present; removing system privileges for "
                        + deletedAppName;
                deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
                PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
                deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
            }
            logCriticalInfo(Log.WARN, msg);
        }
         //遍历mExpectingBetter列表
        for (int i = 0; i < mExpectingBetter.size(); i++) {
            final String packageName = mExpectingBetter.keyAt(i);
            if (!mPackages.containsKey(packageName)) {
                //得到系统App的升级包路径
                final File scanFile = mExpectingBetter.valueAt(i);
                logCriticalInfo(Log.WARN, "Expected better " + packageName
                        + " but never showed up; reverting to system");
                int reparseFlags = mDefParseFlags;
                //3:根据系统App所在的目录设置扫描的解析参数
                if (FileUtils.contains(privilegedAppDir, scanFile)) {
                    reparseFlags = PackageParser.PARSE_IS_SYSTEM
                            | PackageParser.PARSE_IS_SYSTEM_DIR
                            | PackageParser.PARSE_IS_PRIVILEGED;
                } 
                ...
                //将packageName对应的包设置数据(PackageSetting)添加到mSettings的mPackages中
                mSettings.enableSystemPackageLPw(packageName);//4
                try {
                    //扫描系统App的升级包
                    scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 0, null);//5
                } catch (PackageManagerException e) {
                    Slog.e(TAG, "Failed to parse original system package: "
                            + e.getMessage());
                }
            }
        }
    }
   //清除mExpectingBetter列表
    mExpectingBetter.clear();
...
}
  • BOOT_PROGRESS_PMS_SCAN_END:PMS扫描结束

1、如果当前平台SDK版本和上次启动时的SDK版本不同,重新更新APK的授权。
2、如果是第一次启动或者是Android M升级后的第一次启动,需要初始化所有用户定义的默认首选App。
3、OTA升级后的第一次启动,会清除代码缓存目录。
4、把Settings的内容保存到packages.xml中,这样此后PMS再次创建时会读到此前保存的Settings的内容。

//打印扫描结束阶段日志
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                  SystemClock.uptimeMillis());
          Slog.i(TAG, "Time to scan packages: "
                  + ((SystemClock.uptimeMillis()-startTime)/1000f)
                  + " seconds");
          int updateFlags = UPDATE_PERMISSIONS_ALL;
          // 如果当前平台SDK版本和上次启动时的SDK版本不同,重新更新APK的授权
          if (ver.sdkVersion != mSdkVersion) {
              Slog.i(TAG, "Platform changed from " + ver.sdkVersion + " to "
                      + mSdkVersion + "; regranting permissions for internal storage");
              updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
          }
          updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
          ver.sdkVersion = mSdkVersion;
         //如果是第一次启动或者是Android M升级后的第一次启动,需要初始化所有用户定义的默认首选App
          if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {
              for (UserInfo user : sUserManager.getUsers(true)) {
                  mSettings.applyDefaultPreferredAppsLPw(this, user.id);
                  applyFactoryDefaultBrowserLPw(user.id);
                  primeDomainVerificationsLPw(user.id);
              }
          }
         ...
          //OTA后的第一次启动,会清除代码缓存目录。
          if (mIsUpgrade && !onlyCore) {
              Slog.i(TAG, "Build fingerprint changed; clearing code caches");
              for (int i = 0; i < mSettings.mPackages.size(); i++) {
                  final PackageSetting ps = mSettings.mPackages.valueAt(i);
                  if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
                      clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
                              StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
                                      | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
                  }
              }
              ver.fingerprint = Build.FINGERPRINT;
          }
          ...
         // 把Settings的内容保存到packages.xml中
          mSettings.writeLPr();
          Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
  • BOOT_PROGRESS_PMS_READY:PMS就绪

注释1处创建PackageInstallerService,PackageInstallerService是用于管理安装会话的服务,它会为每次安装过程分配一个SessionId。
注释2处进行一次垃圾收集。
注释3处将PackageManagerInternalImpl(PackageManager的本地服务)添加到LocalServices中,
LocalServices用于存储运行在当前的进程中的本地服务。

 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                SystemClock.uptimeMillis());
    ... 
    mInstallerService = new PackageInstallerService(context, this);//1
    ...
    Runtime.getRuntime().gc();//2
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "loadFallbacks");
    FallbackCategoryProvider.loadFallbacks();
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    mInstaller.setWarnIfHeld(mPackages);
    LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());//3
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}

PMS构造方法大致流程:
1、先读取packages.xml文件内容,解析并保存在成员变量mSettings中。
2、扫描设备中的几个分区目录下的应用文件,把扫描结果保存到PMS的mPackages中。这记录的是当前系统中的应用状态信息
3、后面就是对两次的应用状态信息进行:比对、重新调整、扫描特定目录。
4、最后将应用信息重新写回packages.xml文件


带学习:
SystemConfig 对 platform.xml 文件的操作


image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容