PackageManagerService启动分析

PMS系列:
1、PackageManagerService服务框架详解
2、本文PackageManagerService启动分析
3、PackageManagerService之app数据类(Settings)分析
4、PackageManagerService扫描安装apk详解
5、PackageManagerService根据权限等级管理权限(默认赋予apk权限)

PackageManagerService初始化过程

简述Android启动

简单说一下Android的启动过程:
Android基于Linux,前面和Linux大致相同
按下电源 -> BIOS自检 -> 引导程序 -> 启动kernel -> 启动Init进程(system\core\init\init.c) -> 开启虚拟机(Zygotes)
然后
Zygote会startSystemServer,而Systemserver就开始启动framework层的各种公共服务,AMS、WMS、PMS等...

Systemserver启动PMS

从Systemserver.run开始,这里开始启动各种服务

private void run() {
    ...
    // 初始化system Context
    createSystemContext();

    // 创建system manager
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
    ...
    // Start services.
    try {
        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
        // 开始引导Services,Installer创建user/data等目录,
        // 以及MessageMonitorService,AMS,PowerManagerService,LightsService,DisplayManagerService,UserManagerService等
        startBootstrapServices();
        // 核心Services,BatteryService,UsageStatsService,WebViewUpdateService
        startCoreServices();
        // 其他Services,这里启动的服务最多,TelecomLoaderService,CameraService,AccountManagerService等等一系列Service
        startOtherServices();
    } 
    ...
    // Loop forever.
    Looper.loop();
    ...
}

其他服务的启动这里就不展开了,这里开始看PMS的启动

private void startBootstrapServices() {
    ...
    // 创建PMS
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
        mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    ...
    
    // 权限检查,启动其他服务需要授予权限,在这之前需要AMS先做权限检查
    mPackageManagerService.onAmsAddedtoServiceMgr();
    ...
}
    
private void startOtherServices() {
    ...
    //检查system app是否需要更新,需要则更新
    mPackageManagerService.updatePackagesIfNeeded();
    ...

    //检查system app是否需要fs裁剪
    mPackageManagerService.performFstrimIfNeeded();
    ...

    //最后system Ready通知其他服务ready设置相关信息
    mPackageManagerService.systemReady();
    ...
}

详细过程分析

1、创建

PackageManagerService的main中主要进行new PackageManagerService操作,那么从PackageManagerService构建函数开始,这里进行大量的操作

public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        ...
        mContext = context;
        mFactoryTest = factoryTest;
    //是否需要dex化
        mOnlyCore = onlyCore;
    //DisplayMetrics 屏幕信息
        mMetrics = new DisplayMetrics();
    //这个Settings类保存了apk的各种信息
        mSettings = new Settings(mPackages);
    //分配UID,方便权限管理
        mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
    ...
        mInstaller = installer;
    //PackageDexOptimizer初始化,dex优化相关
        mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
                "*dexopt*");
    //移动app的监听
        mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
    //Permission监听
        mOnPermissionChangeListeners = new OnPermissionChangeListeners(
                FgThread.get().getLooper());
    //获得屏幕信息
        getDefaultDisplayMetrics(context, mMetrics);
        ...
        // writer
        synchronized (mPackages) {
        //消息处理线程
            mHandlerThread = new ServiceThread(TAG,
                    Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
            mHandlerThread.start();
            mHandler = new PackageHandler(mHandlerThread.getLooper());
            mProcessLoggingHandler = new ProcessLoggingHandler();
            Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);

        //在手机的data目录下创建app、app-lib、app-ephemeral、app-asec、app-private
            File dataDir = Environment.getDataDirectory();
            mAppInstallDir = new File(dataDir, "app");
            mAppLib32InstallDir = new File(dataDir, "app-lib");
            mEphemeralInstallDir = new File(dataDir, "app-ephemeral");
            mAsecInternalPath = new File(dataDir, "app-asec").getPath();
            mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
        
            sUserManager = new UserManagerService(context, this, mPackages);

            //package manager权限配置
            ArrayMap<String, SystemConfig.PermissionEntry> permConfig
                    = systemConfig.getPermissions();
            for (int i=0; i<permConfig.size(); i++) {
                SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
                BasePermission bp = mSettings.mPermissions.get(perm.name);
                if (bp == null) {
                    bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
                    mSettings.mPermissions.put(perm.name, bp);
                }
                if (perm.gids != null) {
                    bp.setGids(perm.gids, perm.perUser);
                }
            }

           ...
       //保存lib路径
            if (mSharedLibraries.size() > 0) {
                ...
                for (String dexCodeInstructionSet : dexCodeInstructionSets) {
                    for (SharedLibraryEntry libEntry : mSharedLibraries.values()) {
                        final String lib = libEntry.path;
                        if (lib == null) {
                            continue;
                        }

                        try {
                            // Shared libraries do not have profiles so we perform a full
                            // AOT compilation (if needed).
                            int dexoptNeeded = DexFile.getDexOptNeeded(
                                    lib, dexCodeInstructionSet,
                                    getCompilerFilterForReason(REASON_SHARED_APK),
                                    false /* newProfile */);
                //判断是否需要dex优化
                            if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
                                mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet,
                                        dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/,
                                        getCompilerFilterForReason(REASON_SHARED_APK),
                                        StorageManager.UUID_PRIVATE_INTERNAL,
                                        SKIP_SHARED_LIBRARY_CHECK);
                            }
                        } catch (FileNotFoundException e) {
                            Slog.w(TAG, "Library not found: " + lib);
                        } catch (IOException | InstallerException e) {
                            Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
                                    + e.getMessage());
                        }
                    }
                }
            }

        //创建system/framework
            File frameworkDir = new File(Environment.getRootDirectory(), "framework");
        ...
            //从M开始,默认不给权限
            if (mPromoteSystemApps) {
                Iterator<PackageSetting> pkgSettingIter = mSettings.mPackages.values().iterator();
                while (pkgSettingIter.hasNext()) {
                    PackageSetting ps = pkgSettingIter.next();
                    if (isSystemApp(ps)) {
                        mExistingSystemPackages.add(ps.name);
                    }
                }
            }

            //手机overlay资源覆盖包
            File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
            scanDirTracedLI(vendorOverlayDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR
                    | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
        ...
        //接下来扫描安装apk
            //扫描安装/custom/framework下apk
            File customFrameworkDir = new File("/custom/framework");
            scanDirLI(customFrameworkDir, PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags | SCAN_NO_DEX, 0);
            ...
        //此处省略代码为扫描安装各种路径下的apk,和上面代码类似,e.g:system/priv-app、vender/app/等
        ...

            //扫描安装apk,移除已经不在手机里的apk的信息,
            final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
            if (!mOnlyCore) {
                Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
                while (psit.hasNext()) {
                    PackageSetting ps = psit.next();
            ...
                    if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                        /// M: [Operator] Operator apps are belong to system domain, therefore, need prune.
                        /// M: [Operator] We should also consider OTA from old version without mtkFlag
                        if (!isVendorApp(ps) && !locationIsOperator(ps.codePath)) {
                            continue;
                        }
                    }
            ...
                    final PackageParser.Package scannedPkg = mPackages.get(ps.name);
                    if (scannedPkg != null) {
                        ...
                        if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
                            logCriticalInfo(Log.WARN, "Expecting better updated system app for "
                                    + ps.name + "; removing system app.  Last known codePath="
                                    + ps.codePathString + ", installStatus=" + ps.installStatus
                                    + ", versionCode=" + ps.versionCode + "; scanned versionCode="
                                    + scannedPkg.mVersionCode);
                            removePackageLI(scannedPkg, true);
                            mExpectingBetter.put(ps.name, ps.codePath);
                        }

                        continue;
                    }

                    if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
                        psit.remove();
                        logCriticalInfo(Log.WARN, "System package " + ps.name
                                + " no longer exists; it's data will be wiped");
                        // Actual deletion of code and data will be handled by later
                        // reconciliation step
                    } else {
                        final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
                        if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
                            possiblyDeletedUpdatedSystemApps.add(ps.name);
                        }
                    }
                }
            }

            //查找未完成安装的apk
            ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
            for (int i = 0; i < deletePkgsList.size(); i++) {
                ...
                final String packageName = deletePkgsList.get(i).name;
                logCriticalInfo(Log.WARN, "Cleaning up incompletely installed app: " + packageName);
                synchronized (mPackages) {
                    mSettings.removePackageLPw(packageName);
                }
            }

            //删除temp文件
            deleteTempPackageFiles();

            // 删除没有相关软件包的共享用户ID
            mSettings.pruneSharedUsersLPw();

            if (!mOnlyCore) {
                EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                        SystemClock.uptimeMillis());
        //扫描安装/data/app/目录下的apk文件
                scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
        //扫描安装/data/app/app-private/目录下的apk文件
                scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
                        | PackageParser.PARSE_FORWARD_LOCK,
                        scanFlags | SCAN_REQUIRE_KNOWN, 0);
        //扫描安装/data/app-ephemeral/目录
                scanDirLI(mEphemeralInstallDir, mDefParseFlags
                        | PackageParser.PARSE_IS_EPHEMERAL,
                        scanFlags | SCAN_REQUIRE_KNOWN, 0);

                /**
                 * Remove disable package settings for any updated system
                 * apps that were removed via an OTA. If they're not a
                 * previously-updated app, remove them completely.
                 * Otherwise, just revoke their system-level permissions.
                 */
                for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
                    PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
                    mSettings.removeDisabledSystemPackageLPw(deletedAppName);

                    String msg;
                    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 {
                        msg = "Updated system app + " + deletedAppName
                                + " no longer present; removing system privileges for "
                                + deletedAppName;

                        deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;

                        /// M: [Operator] Revoke operator permissions for the original operator package
                        /// under operator folder was gone due to OTA
                        deletedPkg.applicationInfo.flagsEx &= ~ApplicationInfo.FLAG_EX_OPERATOR;

                        PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
                        deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;

                        /// M: [Operator] Revoke vendor permissions
                        deletedPs.pkgFlagsEx &= ~ApplicationInfo.FLAG_EX_OPERATOR;
                    }
                    logCriticalInfo(Log.WARN, msg);
                }

                /**
                 * Make sure all system apps that we expected to appear on
                 * the userdata partition actually showed up. If they never
                 * appeared, crawl back and revive the system version.
                 */
                for (int i = 0; i < mExpectingBetter.size(); i++) {
                    final String packageName = mExpectingBetter.keyAt(i);
                    if (!mPackages.containsKey(packageName)) {
                        final File scanFile = mExpectingBetter.valueAt(i);

                        logCriticalInfo(Log.WARN, "Expected better " + packageName
                                + " but never showed up; reverting to system");

                        int reparseFlags = mDefParseFlags;
                        if (FileUtils.contains(privilegedAppDir, scanFile)) {
                            reparseFlags = PackageParser.PARSE_IS_SYSTEM
                                    | PackageParser.PARSE_IS_SYSTEM_DIR
                                    | PackageParser.PARSE_IS_PRIVILEGED;
                        } else if (FileUtils.contains(systemAppDir, scanFile)) {
                            reparseFlags = PackageParser.PARSE_IS_SYSTEM
                                    | PackageParser.PARSE_IS_SYSTEM_DIR;
                        } else if (FileUtils.contains(vendorAppDir, scanFile)) {
                            reparseFlags = PackageParser.PARSE_IS_SYSTEM
                                    | PackageParser.PARSE_IS_SYSTEM_DIR;
                        } else if (FileUtils.contains(oemAppDir, scanFile)) {
                            reparseFlags = PackageParser.PARSE_IS_SYSTEM
                                    | PackageParser.PARSE_IS_SYSTEM_DIR;
                        } else {
                            Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
                            continue;
                        }

                        mSettings.enableSystemPackageLPw(packageName);

                        try {
                            scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 0, null);
                        } catch (PackageManagerException e) {
                            Slog.e(TAG, "Failed to parse original system package: "
                                    + e.getMessage());
                        }
                    }
                }
            }
            mExpectingBetter.clear();

            //获得开机向导
            mSetupWizardPackage = getSetupWizardPackageName();
            if (mProtectedFilters.size() > 0) {
                ...
                for (ActivityIntentInfo filter : mProtectedFilters) {
                    ...
                    filter.setPriority(0);//设置优先级
                }
            }
            ...
            // 为package更新正确的库文件路径
            updateAllSharedLibrariesLPw();
        ....
            // 更新packages最后使用的时间
            mPackageUsage.readLP();
        ...
            //white/back list
            mForcePermReviewPkgs = new HashSet<String>(
                    Arrays.asList(mContext.getResources().getStringArray(
                            com.mediatek.internal.R.array.force_review_pkgs)));
            ...
            mBlockPermReviewPkgs = new HashSet<String>(
                    Arrays.asList(mContext.getResources().getStringArray(
                            com.mediatek.internal.R.array.block_review_pkgs)));
            ...
            //如果SDK改变,更新权限
            int updateFlags = UPDATE_PERMISSIONS_ALL;
            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;
        ...
            if (!onlyCore && (mPromoteSystemApps || !mRestoredSettings)) {
                for (UserInfo user : sUserManager.getUsers(true)) {
                    mSettings.applyDefaultPreferredAppsLPw(this, user.id);
                    applyFactoryDefaultBrowserLPw(user.id);
                    primeDomainVerificationsLPw(user.id);
                }
            }
            //为启动系统核心应用准备storage
            final int storageFlags;
            if (StorageManager.isFileEncryptedNativeOrEmulated()) {
                storageFlags = StorageManager.FLAG_STORAGE_DE;
            } else {
                storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
            }
            reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL, UserHandle.USER_SYSTEM,
                    storageFlags);

            //以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)) {
                        // No apps are running this early, so no need to freeze
                        clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
                                StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
                                        | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
                    }
                }
                ver.fingerprint = Build.FINGERPRINT;
            }
        
        //检查默认浏览器
            checkDefaultBrowser();
        ...
        
        mSettings.writeLPr();
        //第一次开机,升级,执行dexopt
            if ((isFirstBoot() || isUpgrade() || VMRuntime.didPruneDalvikCache()) && !onlyCore) {
                long start = System.nanoTime();
                List<PackageParser.Package> coreApps = new ArrayList<>();
                for (PackageParser.Package pkg : mPackages.values()) {
                    if (pkg.coreApp) {
                        coreApps.add(pkg);
                    }
                }

                int[] stats = performDexOpt(coreApps, false,
                        getCompilerFilterForReason(REASON_CORE_APP));

                final int elapsedTimeSeconds =
                        (int) TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start);
                MetricsLogger.histogram(mContext, "opt_coreapps_time_s", elapsedTimeSeconds);
        ...
            }
        ...
        //初始化PackageInstallerService
            mInstallerService = new PackageInstallerService(context, this);

        //为系统组件公开私有服务
        LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());

        //permission记录控制
        if (CtaUtils.isCtaSupported()) {
            mPermRecordController = new PermissionRecordController(mContext);
        }
    }

创建过程总结:
1、准备:创建Settings保存apk信息,分配UID,PackageDexOptimizer初始化,移动app的监听,Permission监听,启动消息线程
2、目录创建:data目录创建,保存lib路径,创建system/framework
3、扫描并安装:overlay资源覆盖包,扫描各种路径下的apk信息,安装,删除temp文件
4、更新:获得开机向导,跟新库文件路径,更新package使用时间,更新权限
5、准备完毕:准备storage,检查默认浏览器,执行dexopt,初始化PackageInstallerService,公开私有服务

小结

PMS启动分析到此结束,主要过程就是PMS的创建,这里只是对整个初始化过程进行一个整体的小结。把握PMS的整体流程,后续文章再对PMS进行细节分析。

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

推荐阅读更多精彩内容