Android FrameWork--ActivityManageService启动

1、概述

我们从上一篇文章知道在SystemServer进程启动之后,就会启动很多系统服务,我们看到源码部分,创建系统服务管理者之后,通过调用startBootstrapServices、startBootstrapServices、startCoreService三个函数。启动了系统的一些关键服务,也就是其他服务需要依赖的服务最早执行,还有核心服务、其他服务。

.....
        // Create the system service manager.
      //创建系统服务管理者
   mSystemServiceManager = new SystemServiceManager(mSystemContext);
    mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
.....

 // Start services.启动服务
        try {
            traceBeginAndSlog("StartServices");
            //启动系统关键服务
            startBootstrapServices();
           //核心服务
            startCoreServices();
            //其他服务
            startOtherServices();
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            traceEnd();
        }

2、ActivityManageService的创建和启动

下面我们看到启动关键服务的startBootstrapServices的方法里。

 private void startBootstrapServices() {

          .....
        //0、启动安装器服务
        Installer installer = mSystemServiceManager.startService(Installer.class);
          .....
        //1、启动ActivityManagerService服务
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
      //2、为AMS设置系统服务管理者
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
      //3、为AMS设置安装器
        mActivityManagerService.setInstaller(installer);
        ....
       //4、初始化PowerManagement相关
       mActivityManagerService.initPowerManagement();
      ......
      //5、设置系统进程
       mActivityManagerService.setSystemProcess();
      ..........
      mActivityManagerService.setUsageStatsManager(
                LocalServices.getService(UsageStatsManagerInternal.class));

}

2.1、SystemServiceManager.startService

SystemServiceManager中的startService方法,创建并启动了ActivityManagerService服务。主要通过是调用了SystemServiceManager的startService函数,传入了Lifecycle.class,并通过getService返回ActivityManagerService实例

mActivityManagerService = mSystemServiceManager.startService(
               ActivityManagerService.Lifecycle.class).getService();

我们来看具体的startService方法

public <T extends SystemService> T startService(Class<T> serviceClass) {
        try {
            final String name = serviceClass.getName();
            Slog.i(TAG, "Starting " + name);
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + name);
            // Create the service.
            if (!SystemService.class.isAssignableFrom(serviceClass)) {
                throw new RuntimeException("Failed to create " + name
                        + ": service must extend " + SystemService.class.getName());
            }
            final T service;
        .............
          //通过反射获取构造函数,并创建实例。
              Constructor<T> constructor = serviceClass.getConstructor(Context.class);
               service = constructor.newInstance(mContext);
            ................
            //调用startService并传入Lifecycle实例
            startService(service);
            return service;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
    }
    public void startService(@NonNull final SystemService service) {
        // Register it.
        mServices.add(service);
        // Start it.
        long time = SystemClock.elapsedRealtime();
        try {
            service.onStart();
        } catch (RuntimeException ex) {
            throw new RuntimeException("Failed to start service " + service.getClass().getName()
                    + ": onStart threw an exception", ex);
        }
        warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
    }

通过反射获取Lifecycle构造函数,并创建Lifecycle实例。接着调用startService方法,传入Lifecycle实例。并返回当前Lifecycle实例。在startService中又调用了Lifecycle实例的onStart方法。我们再看看Lifecycle类

 public static final class Lifecycle extends SystemService {
        private final ActivityManagerService mService;

        public Lifecycle(Context context) {
            super(context);
            mService = new ActivityManagerService(context);
        }
        @Override
        public void onStart() {
            mService.start();
        }
        @Override
        public void onCleanupUser(int userId) {
            mService.mBatteryStatsService.onCleanupUser(userId);
        }

        public ActivityManagerService getService() {
            return mService;
        }
    }

我们看到在Lifecycle 的构造函数中创建了ActivityManagerService实例,接着在onStart的时候,就调用了ActivityManagerService的start函数,其实这里也就是通过一种静态代理的方式创建ActivityManagerService实例并调用ActivityManagerService的start方法,启动ActivityManagerService服务。接着在Lifecycle 中暴露getService方法,返回了ActivityManagerService实例。所以再一开始的
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
我们就拿到了ActivityManagerService的实例,因此下面我们来分析ActivityManagerService创建实例的构造函数和start函数

2.2、ActivityManagerService的构造函数

public ActivityManagerService(Context systemContext) {
        LockGuard.installLock(this, LockGuard.INDEX_ACTIVITY);
        mInjector = new Injector();
        mContext = systemContext;

        mFactoryTest = FactoryTest.getMode();
        mSystemThread = ActivityThread.currentActivityThread();
        mUiContext = mSystemThread.getSystemUiContext();

        Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());

        mPermissionReviewRequired = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_permissionReviewRequired);
        //1、创建名为ActivityManagerService的前台线程,并start启动
        mHandlerThread = new ServiceThread(TAG,
                THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
        mHandlerThread.start();
        //2、创建ActivityManagerService线程的Handler
        mHandler = new MainHandler(mHandlerThread.getLooper());
        //3、创建UiThread线程,并初始化该线程的Handler
        mUiHandler = mInjector.getUiHandler(this);

        mConstants = new ActivityManagerConstants(this, mHandler);

        /* static; one-time init here */
        if (sKillHandler == null) {
            sKillThread = new ServiceThread(TAG + ":kill",
                    THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
            sKillThread.start();
            sKillHandler = new KillHandler(sKillThread.getLooper());
        }
        //4、创建运行在前台的广播接收器,10S超时
        mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
                "foreground", BROADCAST_FG_TIMEOUT, false);
      //5、后台广播接收器,60S超时
        mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
                "background", BROADCAST_BG_TIMEOUT, true);
        mBroadcastQueues[0] = mFgBroadcastQueue;
        mBroadcastQueues[1] = mBgBroadcastQueue;

        mServices = new ActiveServices(this);
        mProviderMap = new ProviderMap(this);
        mAppErrors = new AppErrors(mUiContext, this);

        // TODO: Move creation of battery stats service outside of activity manager service.
        //6、创建system目录
        File dataDir = Environment.getDataDirectory();
        File systemDir = new File(dataDir, "system");
        systemDir.mkdirs();
       //7、启动电池服务
        mBatteryStatsService = new BatteryStatsService(systemContext, systemDir, mHandler);
        mBatteryStatsService.getActiveStatistics().readLocked();
        mBatteryStatsService.scheduleWriteToDisk();
        mOnBattery = DEBUG_POWER ? true
                : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
        mBatteryStatsService.getActiveStatistics().setCallback(this);
        //8、创建进程统计服务,统计信息保存在systemDir目录的procstats文件内
        mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));

       ..................
        //9、创建StackSupervisor实例
        mStackSupervisor = createStackSupervisor();
        mStackSupervisor.onConfigurationChanged(mTempConfig);
        mKeyguardController = mStackSupervisor.mKeyguardController;
        mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
        mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
        mTaskChangeNotificationController =
                new TaskChangeNotificationController(this, mStackSupervisor, mHandler);
        mActivityStarter = new ActivityStarter(this, mStackSupervisor);
        mRecentTasks = new RecentTasks(this, mStackSupervisor);
         //10、创建CPU统计线程
        mProcessCpuThread = new Thread("CpuTracker") {
            @Override
            public void run() {
                synchronized (mProcessCpuTracker) {
                    mProcessCpuInitLatch.countDown();
                  //11、统计CPU使用情况
                    mProcessCpuTracker.init();
                }
                while (true) {
                    try {
                        try {
                            synchronized(this) {
                                final long now = SystemClock.uptimeMillis();
                                long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
                                long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
                                //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
                                //        + ", write delay=" + nextWriteDelay);
                                if (nextWriteDelay < nextCpuDelay) {
                                    nextCpuDelay = nextWriteDelay;
                                }
                                if (nextCpuDelay > 0) {
                                    mProcessCpuMutexFree.set(true);
                                    this.wait(nextCpuDelay);
                                }
                            }
                        } catch (InterruptedException e) {
                        }
                        //12、更新CPU状态
                        updateCpuStatsNow();
                    } catch (Exception e) {
                        Slog.e(TAG, "Unexpected exception collecting process stats", e);
                    }
                }
            }
        };

        Watchdog.getInstance().addMonitor(this);
        Watchdog.getInstance().addThread(mHandler);
    }

2.3、ActivityManagerService的start函数

private void start() {    
        //移除所有进程组
        removeAllProcessGroups();
      //CPU统计的线程启动
        mProcessCpuThread.start();
        //启动电池服务
        mBatteryStatsService.publish();
        mAppOpsService.publish(mContext);
        Slog.d("AppOps", "AppOpsService published");
      //添加到本地服务LocalServices中
        LocalServices.addService(ActivityManagerInternal.class, new LocalService());
       
        try {
            mProcessCpuInitLatch.await();
        } catch (InterruptedException e) {
            Slog.wtf(TAG, "Interrupted wait during start", e);
            Thread.currentThread().interrupt();
            throw new IllegalStateException("Interrupted wait during start");
        }
    }

3、将ActivityManagerService注册服务到ServiceManager

以上ActivityManagerService就被创建和启动了,回到startBootstrapServices方法里,我们知道在startBootstrapServices方法里创建启动ActivityManagerService之后,又通过ActivityManagerService的实例调用了其setSystemProcess方法,

 public void setSystemProcess() {
        try {
            //注册各种服务到ServiceManager中
           //3.1、将ActivityManagerService注册到ServiceManager中
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
            ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
            ServiceManager.addService("meminfo", new MemBinder(this));
            ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
            ServiceManager.addService("dbinfo", new DbBinder(this));
            if (MONITOR_CPU_USAGE) {
                ServiceManager.addService("cpuinfo", new CpuBinder(this));
            }
            ServiceManager.addService("permission", new PermissionController(this));
            ServiceManager.addService("processinfo", new ProcessInfoService(this));

            ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
                    "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
          //详见3.2
            mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());

            synchronized (this) {
                ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
                app.persistent = true;
                app.pid = MY_PID;
                app.maxAdj = ProcessList.SYSTEM_ADJ;
                app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
                synchronized (mPidsSelfLocked) {
                    mPidsSelfLocked.put(app.pid, app);
                }
                updateLruProcessLocked(app, false, null);
                updateOomAdjLocked();
            }
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException(
                    "Unable to find android system package", e);
        }
    }

以上主要是把各种服务注册到ServiceManager中,我们看到最核心的ActivityManagerService服务此时也注册到了ServiceManager中,注册服务的名字为activity,这里很关键,作为其他进程和SytemServer进程通信的桥梁。例如我们的APP进程就是可以使用ServiceManager通过服务的名字获取到ActivityManagerService作为通信媒介,而我们看到ActivityManagerService本身又继承了Binder。

public class ActivityManagerService extends IActivityManager.Stub
public static abstract class Stub extends android.os.Binder implements android.app.IActivityManager

这样APP进程就可以通过获取到的ActivityManagerService实现跨进程通信。例如最常见的我们在APP进程启动一个Actvity。

int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
  public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            }

就是首先通过ServiceManager获取到我们的ActivityManagerService,然后转换为IActivityManager 对象。通过调用IActivityManager 接口的startActivity函数,最终实现跨进程通信,就调用到了ActivityManagerService的startActivity函数。

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

详细Activity的启动,我们后续在介绍,在这里我们知道,当创建启动ActivityManagerService之后,会通过一个名字注册到ServiceManager中,其他进程使用ServiceManager便可以通过名字获取到注册的服务,实现跨进程通信。

4、mActivityManagerService.systemReady--SystemServer进程准备好了

在启动了系统的关键和核心服务之后,接着又通过startOtherServices启动一些其他的服务。这样我们把需要的系统服务启动好了,我们在startOtherServices函数的最后,看到 mActivityManagerService.systemReady这个函数。

 // We now tell the activity manager it is okay to run third party
        // code.  It will call back into us once it has gotten to the state
        // where third party code can really run (but before it has actually
        // started launching the initial applications), for us to complete our
        // initialization.
        mActivityManagerService.systemReady(() -> {
      }

从注释上说明了我们可以告诉活动管理器此时SystemServer进程已经启动好了,此时可以运行第三方的程序代码了,比如我们的APP程序。我们来看看systemReady函数内和回调函数中做了那些操作?

    public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
     ...............
           startHomeActivityLocked(currentUserId, "systemReady");
    ...............

      }

boolean startHomeActivityLocked(int userId, String reason) {
        if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                && mTopAction == null) {
            // We are running in factory test mode, but unable to find
            // the factory test app, so just sit around displaying the
            // error message and don't try to start anything.
            return false;
        }
        //创建Intent对象
        Intent intent = getHomeIntent();
        ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
        if (aInfo != null) {
            intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
            // Don't do this if the home app is currently being
            // instrumented.
            aInfo = new ActivityInfo(aInfo);
            aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
            ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                    aInfo.applicationInfo.uid, true);
            if (app == null || app.instr == null) {
                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
                // For ANR debugging to verify if the user activity is the one that actually
                // launched.
                final String myReason = reason + ":" + userId + ":" + resolvedUserId;
              //启动HomeActivtity。
                mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);
            }
        } else {
            Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
        }

        return true;
    }

调用startHomeActivityLocked。启动Home类型的Activity,并且传入的reason参数是systemReady,也就说明了此时SystemServer已经准备好了,可以启动第一个Home类型的Activity了。在startHomeActivityLocked函数里我们首先调用getHomeIntent函数创建Intent对象,用于启动Home类型的Activity。我们看getHomeIntent函数。

    Intent getHomeIntent() {
      // public static final String ACTION_MAIN = "android.intent.action.MAIN";
        Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
        intent.setComponent(mTopComponent);
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
          //    public static final String CATEGORY_HOME = "android.intent.category.HOME";
            intent.addCategory(Intent.CATEGORY_HOME);
        }
        return intent;
    }

我们看到Intent的action为 "android.intent.action.MAIN",category是android.intent.category.HOME。Launcher和FallbackHome这两个Activity都能匹配到。

  <activity android:name=".FallbackHome"
                  android:excludeFromRecents="true"
                  android:label=""
                  android:screenOrientation="nosensor"
                  android:theme="@style/FallbackHome">
            <intent-filter android:priority="-1000">
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
   <activity
            android:name="com.android.launcher2.Launcher"
            android:launchMode="singleTask"
            android:clearTaskOnLaunch="true"
            android:stateNotNeeded="true"
            android:resumeWhilePausing="true"
            android:theme="@style/Theme"
            android:windowSoftInputMode="adjustPan"
            android:screenOrientation="nosensor">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.MONKEY"/>
            </intent-filter>
        </activity>

而在FallbackHome中我们看到android:priority="-1000",优先级很高,因此可以猜到第一个Activity启动的就是FallbackHome。当然我们也可以通过编译系统源码,打印日志的方式。通过打印我们也可以看到

    行 1604: 04-06 21:46:42.667  1767  1767 D MyTest  : FallbackHome onCreate: 
    行 1608: 04-06 21:46:42.672  1767  1767 D MyTest  : FallbackHome onResume: 
    行 2400: 04-06 21:46:16.118  1767  1767 D MyTest  : FallbackHome onReceive: 
    行 2402: 04-06 21:46:16.119  1767  1767 D MyTest  : User unlocked and real home found; let's go!
    行 2407: 04-06 21:46:16.166  1767  1767 D MyTest  : FallbackHome onPause: 
    行 2445: 04-06 21:46:16.600  2064  2064 D MyTest  : Launcher2 onCreate: 
    行 2573: 04-06 21:46:17.576  1767  1767 D MyTest  : FallbackHome onDestroy: 
 

首先会启动我们的FallbackHome ,在FallbackHome 解锁之后就会启动我们的Launcher2 ,也就是我们平时习惯说的系统桌面。

5、小结

在ActivityManagerService中做了很多很的工作,总共代码有2W多行,没法每个函数都分析清楚。我们大概小结ActivityManagerService的启动流程

  • 在SystemServer中创建系统服务器管理者SystemServiceManager,并通过它启动三种类型的服务:关键服务、核心服务器、其他服务
  • 在启动关键服务器中创建启动了ActivityManagerService服务
  • 将ActivityManagerService注册到ServiceManager中,名字为activity。其他进程就可以通过名字检索到ActivityManagerService,而ActivityManagerService本身继承了Binder,从而用于实现跨进程通信。
  • 在三种类型的服务中启动了很多很多具体的服务,在启动这些服务之后,通过ActivityManagerService的systemReady,表示SystemServer进程准备好了,此时可以运行第三方的代码,比如我的APP应用程序。
  • SystemReady之后,就开始启动我们的第一个Activity:FallbackHome ,在FallbackHome 被解锁之后,接着就会启动我们的Launcher2 ,也就是我们的桌面Activity。
    下一篇我们将介绍第一个Activity-FallbackHome 做了什么?Launcher2 是怎么启动的,桌面程序进程是怎么被启动的。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容