209. 长度*小的子数组(JS实现)

209. 长度*小的子数组(JS实现)
1 题目
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度*小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
示例:
输入:s = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度*小的子数组。
链接:https://leetcode-cn.com/problems/minimum-size-subarray-sum
2 思路
这道题我是用双指针的方法遍历整个数组来获取长度*小的子数组的
3代码
/**
 * @param {number} s
 * @param {number[]} nums
 * @return {number}
 */
var minSubArrayLen = function(s, nums) {
  if (nums.length === 0) return 0;
  if (Math.min(…nums) >= s) return 1;
  let len;
  let low=0, high=1;
  while(low < nums.length) {
    let sum = 0;
    for (let i=low; i<high; i++) {
      sum += nums[i];
    }
    if (sum >= s) {
      let tempLen = high – low;
      len = len ? Math.min(len, tempLen) : tempLen;
      if (tempLen === 1) break;
      low++;
    } else {
      high++;
      if (high > nums.length) break;
    }
  }
  return len || 0;
};

个人或是公司如何选择适合自己的云服务器?

近年来,国内云计算的快速发展催动了一个新时代的产生。云计算正不断渗透到各行各业,不管是大型企业还是中小型企业都在争相拥抱云。与此同时,企业内部的IT基础架构正在发生变化,云服务器作为这个时代的产物早已引起人们的关注。

云服务器又叫云计算服务器或云主机。云服务器使用了云计算技术,整合了数据中心三大核心要素:计算、网络与存储。云服务器基于集群服务器技术,虚拟出多个类似独立服务器的部分,具有很高的安全稳定性。

因为云服务器是新时代产物,大多数中小企业对其了解并不深刻,在选择过程中存在很多问题,可能会导致自己的业务在运行过程中出现故障。

对于中小企业来说,在选购云服务器时应该从自身需求出发,应该考虑以下问题:

从需求出发,你是否真的需要云服务器?

中小企业在选择购买云服务器之前,需要对自己的业务需求进行评估,看看自己是否真的需要使用云服务器。

通常情况下,云服务器提供了比传统物理服务器更高的性价比,能够支持企业实现快速分布式部署。如果你对这些方面有非常高的要求的话,可以考虑使用云服务器。

另外,根据云服务器自身的优势,对业务的弹性扩展能力有较高的要求,或者对系统高可用性以及对数据进行快速恢复需求的用户来说,云服务器也是其理想的选择。

云服务器支持的应用比较广泛,包括电子商务、企业网站、OA系统、企业ERP/CRM管理软件、论坛和SNS等等。

选购的云服务器是否具备了必要的功能?

中小企业在采购云服务器之前需要具备一些相关知识。比如云服务器能够实现哪些有别于传统物理服务器的功能?

较传统物理服务器来说,云服务器更具有安全性。因为云服务器具有防ARP攻击和MAC欺骗功能,可进行快照备份,保证数据永久不丢失。而且云服务器比传统的物理服务器更加可靠,因为其是基于服务器集群的,因此具有较高的硬件冗余,能大大降低故障发生率,而传统的服务器会因为资源占用过高或带宽不足时出现宕机情况。

另外,云服务器还具有故障自动迁移功能,如果一台云服务器出现故障,其上面的应用会自动迁移到其他云服务器上面,从而保证业务能够正常运行。

在数据备份方面,云服务器能实现快照备份,当主机出现故障时,能够一键恢复故障前的所有数据。

另一方面,企业用户可以根据自身需要实现实时在线增添服务器配置,一键轻松实现服务器扩展。而过去,企业则需要重新购置新的服务器,然后进行安装部署等。云服务器帮助企业免去了这些麻烦,轻松实现平滑升级。

你的云服务器提供商选对了吗?

中小企业在购买合适的云服务器时需要考虑到厂家这一重要因素,尽量选用知名、正规的云服务器提供商,同时要做到货比三家。

目前很多IT行业服务器巨头已经开始提供有质量保证的云计算产品。互联网企业、电子商务、论坛和社交等中小企业均可以根据不同需求选择合适自己的云服务器。

另外,不得不提的一点是服务商的售后服务情况。

*后,中小企业在云时代的业务发展迅速,因此在购买云服务器时既要考虑到目前运行的日常应用需求,又要立足于企业未来几年的业务发展趋势,避免因升级空间不足而造成性能瓶颈。

浅析企业网站应该如何选择适合自己的服务器?

众所周知,在网站建设之初处企业应该首先决定好选购什么样式的网站服务器,网站服务器对网站的加载速度起到决定性作用,如果无法保证网站的加载速度这对网站后期的优化工作进行也是具有难度的,那么企业到底应该如何选择网站服务器呢?下面就针对该问题进行详细分析,希望可以帮助到大家哦。

1、重要参数

通常网站服务器大多是使用CPU的类型,不过服务器还有其他两种架构可选分别为RISC和CISC。前者是以使用RISC技术为主更为高档,普遍使用Unix操作系统;而后者CISC广受中小企业所信赖,可以说是一款中低档型更为接地气的服务器,大多是以Linux操作系统或者是Windows操作系统为主。

2、服务器的CPU

服务器对网站的重要性想必大家都了解,而CPU对服务器的影响却是非同小可,就像是人类大脑一样的存在。因此,服务器CPU的质量从根本上就决定了网站服务器性能的好坏,同理,如果服务器的CPU缓存数量越大,频率越高也能带动服务器运行的速度,连带着网站的打开速度也会越来越快,就能进一步提升网站用户的使用体验,可谓是一举多得。

3、服务器的内存

许多服务器普遍使用的都是专用的ECC校验内存,这也表明在使用ECC内存的同时要学会搭配不同的CPU系统,如果想要让自家的服务器有一个良好的使用性能体验就要加大服务器的内存数量。毕竟对于网络服务商户们来说,服务器的内存大小显得十分重要,比如说*低的配型都应该具备2GB的内存,其他服务器配型可根据不同企业的需求进行相应的增加。

4、服务器的网卡

众多服务器在投入使用前*基本的需求是需要满足为计算机提供相应的服务,因此,服务器需要拥有与其他计算机进行通讯的功能,这一点就对服务器的处理能力有着不小的挑战。如果服务器不具备与其他计算机的通讯功能,就不能面对客户端需求及时作出回应,这将对网络信息输送产生很大影响。因此,为了保证满足服务器快速传送网络信息的需求,一定要给服务器配备一个千兆卡以上的网卡,这才能够给予服务器*基本的服务保障。

总而言之,企业网站在选择网站服务器时一定要擦亮眼睛,对于不了解的问题更要悉心请教,网站服务器之于网站意义非凡,希望今天所分享的内容可以帮助到企业完成对网站服务器的选择哦。

Activity启动流程–Activity Task的调度算法

前面介绍了Activity的详细启动流程,提到ActivityStack类的startActivityUncheckedLocked方法负责调度ActivityRecord和Task,并且调度算法非常复杂,需结合实际场景分析调度算法。本篇博客将介绍startActivityUncheckedLocked方法的具体实现,本结合实际场景分析调度算法。

startActivityUncheckedLocked方法的具体实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
final int startActivityUncheckedLocked(ActivityRecord r,
        ActivityRecord sourceRecord, int startFlags, boolean doResume,
        Bundle options) {
    //... 
    //如果从Launcher程序启动应用,launchFlags为
    //FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 
    //否则一般情况下launcheFlags为0,除非启动Activity时设置了特殊的flag
    int launchFlags = intent.getFlags();      
    //启动Activity时默认不会设置FLAG_ACTIVITY_PREVIOUS_IS_TOP 
    //故此notTop默认情况下会是null
    ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
            != 0 ? r : null; 
    //默认情况下startFlags不会设置START_FLAG_ONLY_IF_NEEDED
    // If the onlyIfNeeded flag is set, then we can do this if the activity
    // being launched is the same as the one making the call...  or, as
    // a special case, if we do not know the caller then we count the
    // current top activity as the caller.
    if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
         //...默认情况下这里的代码不会执行
    }    
    //根据被启动的Activity和sourceRecord设置标志
    //launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK
    //如果从通知栏启动应用 sourceRecord == null
    if (sourceRecord == null) {
        // This activity is not being started from another...  in this
        // case we -always- start a new task.
        if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
            Slog.w(TAG, "startActivity called from non-Activity context;" 
                  +"forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
                  + intent);
            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
        }
    } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
        // The original activity who is starting us is running as a single
        // instance...  this new activity it is starting must go on its
        // own task.
        launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
    } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
        // The activity being started is a single instance...  it always
        // gets launched into its own task.
        launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
    }
    
  //一般情况下r.resultTo 不为null,它是启动该Activity的Activity,
  //如果从通知栏启动Activity 则r.result为null
  if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
      //...
      r.resultTo = null;
  }       
    //addingToTask 如果为true表示正在添加至某个task,
    //  后续需要将r添加至sourceRecord所在的task
    boolean addingToTask = false;
    //movedHome表示是否移动home task
    boolean movedHome = false;
    //reuseTask 如果不为null,则表示已存在task,会重用这个task,
    //                      但是这个Task里的所有Activity会被清除掉,
    //                      需要将r加入这个task  
    TaskRecord reuseTask = null;       
    if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
            (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
        //从通知栏启动时r.resultTo == null
        //如果launchFlags设置了FLAG_ACTIVITY_NEW_TASK,r.resultTo也会为null
        if (r.resultTo == null) {
            //查找ActivityRecord栈,看要启动的activity是否已有相关task,
            //如果已经有相关task,则不需要创建新的task,可以使用已有的task
            //如果要启动的activity的启动模式是LAUNCH_SINGLE_INSTANCE,
            //则使用快速查找方法findTaskLocked,否则使用慢速查找方法findActivityLocked
            //因为如果启动模式是LAUNCH_SINGLE_INSTANCE,则这个activity只会在一个单独的Task里
            //故此查找时,可以以task为单位进行查找和比较,这样比较快
            //查找得到的结果taskTop是相关task的栈顶的ActivityRecord               
            // See if there is a task to bring to the front.  If this is
            // a SINGLE_INSTANCE activity, there can be one and only one
            // instance of it in the history, and it is always in its own
            // unique task, so we do a special search.
            ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
                    ? findTaskLocked(intent, r.info)
                    : findActivityLocked(intent, r.info);
            //找到了相关task        
            if (taskTop != null) {
                //重设task的intent
                if (taskTop.task.intent == null) {
                    // This task was started because of movement of
                    // the activity based on affinity...  now that we
                    // are actually launching it, we can assign the
                    // base intent.
                    taskTop.task.setIntent(intent, r.info);
                }
                //如果目标task不在栈顶,
                //则先将Home task移动到栈顶(实际上只有当启动Activity设置的Flag同时设置了
                //FLAG_ACTIVITY_TASK_ON_HOME和FLAG_ACTIVITY_NEW_TASK才会移动home task,
                //否则不会移动home task),
                //然后再将目标task移动到栈顶
                // If the target task is not in the front, then we need
                // to bring it to the front...  except...  well, with
                // SINGLE_TASK_LAUNCH it's not entirely clear.  We'd like
                // to have the same behavior as if a new instance was
                // being started, which means not bringing it to the front
                // if the caller is not itself in the front.
                ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop);
                if (curTop != null && curTop.task != taskTop.task) {
                    r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
                    boolean callerAtFront = sourceRecord == null
                            || curTop.task == sourceRecord.task;
                    if (callerAtFront) {
                        // We really do want to push this one into the
                        // user's face, right now.
                        movedHome = true;
                        moveHomeToFrontFromLaunchLocked(launchFlags);
                        moveTaskToFrontLocked(taskTop.task, r, options);
                        options = null;
                    }
                }
                //如果launchFlags设置了FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,则会重置task 
                //从Launcher应用程序启动应用会设置FLAG_ACTIVITY_RESET_TASK_IF_NEEDED       
                // If the caller has requested that the target task be
                // reset, then do so.
                if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
                    taskTop = resetTaskIfNeededLocked(taskTop, r);
                }
                //... 一般情况下startFlags 不会设置 START_FLAG_ONLY_IF_NEEDED
                if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED)  != 0) {
                    //...
                }
                // ==================================                                 
                //默认情况下不会设置 Intent.FLAG_ACTIVITY_CLEAR_TASK
                if ((launchFlags &
                        (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
                        == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
                    // The caller has requested to completely replace any
                    // existing task with its new activity.  Well that should
                    // not be too hard...
                    reuseTask = taskTop.task;
                    performClearTaskLocked(taskTop.task.taskId);
                    reuseTask.setIntent(r.intent, r.info);
                } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
                        || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
                        || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
                    //默认情况下launchFlags不会设置FLAG_ACTIVITY_CLEAR_TOP
                    //但是如果被启动的activity的启动模式是singleTask或者singleInstance,
                    //也会进入该分支
                    // In this situation we want to remove all activities
                    // from the task up to the one being started.  In most
                    // cases this means we are resetting the task to its
                    // initial state.
                    //清除r所在的task 在r之上的所有activity, 
                    //该task里r和在r下的activity不会被清除
                    ActivityRecord top = performClearTaskLocked(
                            taskTop.task.taskId, r, launchFlags);
                    if (top != null) {
                        if (top.frontOfTask) {
                            // Activity aliases may mean we use different
                            // intents for the top activity, so make sure
                            // the task now has the identity of the new
                            // intent.
                            top.task.setIntent(r.intent, r.info);
                        }
                        logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
                        top.deliverNewIntentLocked(callingUid, r.intent);
                    } else {
                        // A special case: we need to
                        // start the activity because it is not currently
                        // running, and the caller has asked to clear the
                        // current task to have this activity at the top.
                        addingToTask = true;
                        // Now pretend like this activity is being started
                        // by the top of its task, so it is put in the
                        // right place.
                        sourceRecord = taskTop;
                    }
                } else if (r.realActivity.equals(taskTop.task.realActivity)) {
                    // In this case the top activity on the task is the
                    // same as the one being launched, so we take that
                    // as a request to bring the task to the foreground.
                    // If the top activity in the task is the root
                    // activity, deliver this new intent to it if it
                    // desires.
                    if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
                            && taskTop.realActivity.equals(r.realActivity)) {
                        logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
                        if (taskTop.frontOfTask) {
                            taskTop.task.setIntent(r.intent, r.info);
                        }
                        taskTop.deliverNewIntentLocked(callingUid, r.intent);
                    } else if (!r.intent.filterEquals(taskTop.task.intent)) {
                        // In this case we are launching the root activity
                        // of the task, but with a different intent.  We
                        // should start a new instance on top.
                        addingToTask = true;
                        sourceRecord = taskTop;
                    }
                } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
                    // In this case an activity is being launched in to an
                    // existing task, without resetting that task.  This
                    // is typically the situation of launching an activity
                    // from a notification or shortcut.  We want to place
                    // the new activity on top of the current task.
                    addingToTask = true;
                    sourceRecord = taskTop;
                } else if (!taskTop.task.rootWasReset) {
                    //进入该分支的情况比较少
                    // In this case we are launching in to an existing task
                    // that has not yet been started from its front door.
                    // The current task has been brought to the front.
                    // Ideally, we'd probably like to place this new task
                    // at the bottom of its stack, but that's a little hard
                    // to do with the current organization of the code so
                    // for now we'll just drop it.
                    taskTop.task.setIntent(r.intent, r.info);
                }   
                // ================================== end
                //如果没有正在添加至某个Task, 并且不用加入一个已清除所有Activity的Task
                //此时只需要显示栈顶Activity即可              
                if (!addingToTask && reuseTask == null) {
                    // We didn't do anything...  but it was needed (a.k.a., client
                    // don't use that intent!)  And for paranoia, make
                    // sure we have correctly resumed the top activity.
                    if (doResume) {
                        resumeTopActivityLocked(null, options);
                    } else {
                        ActivityOptions.abort(options);
                    }
                    return ActivityManager.START_TASK_TO_FRONT;
                }
            }
        }
    } 
    //...  
    if (r.packageName != null) {
        // If the activity being launched is the same as the one currently
        // at the top, then we need to check if it should only be launched
        // once.
        ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);
        if (top != null && r.resultTo == null) {
            if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
                if (top.app != null && top.app.thread != null) {
                    if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
                        || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
                        || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
                        //singleTop启动模式或者singleTask启动模式,
                        //并且task栈顶的activity是要启动的activity,则先显示Activity
                        //然后调用该Activity的onNewIntent方法
                        logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
                        // For paranoia, make sure we have correctly
                        // resumed the top activity.
                        //先显示Activity
                        if (doResume) {
                            resumeTopActivityLocked(null);
                        }
                        ActivityOptions.abort(options);
                        if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
                            // We don't need to start a new activity, and
                            // the client said not to do anything if that
                            // is the case, so this is it!
                            return ActivityManager.START_RETURN_INTENT_TO_CALLER;
                        }
                        //然后调用已显示activity的onNewIntent方法
                        top.deliverNewIntentLocked(callingUid, r.intent);
                        return ActivityManager.START_DELIVERED_TO_TOP;
                    }
                }
            }
        }

    } else {
        if (r.resultTo != null) {
            sendActivityResultLocked(-1,
                    r.resultTo, r.resultWho, r.requestCode,
                Activity.RESULT_CANCELED, null);
        }
        ActivityOptions.abort(options);
        return ActivityManager.START_CLASS_NOT_FOUND;
    }
    boolean newTask = false;
    boolean keepCurTransition = false;
    // Should this be considered a new task?
    if (r.resultTo == null && !addingToTask
            && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
        if (reuseTask == null) {
             //创建新的task
            // todo: should do better management of integers.
            mService.mCurTask++;
            if (mService.mCurTask <= 0) {
                mService.mCurTask = 1;
            }
            r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null, true);
            if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
                    + " in new task " + r.task);
        } else {
           //重复利用先前的task,该task里的所有acitivity已经被清空
            r.setTask(reuseTask, reuseTask, true);
        }
        newTask = true;
        if (!movedHome) {
            moveHomeToFrontFromLaunchLocked(launchFlags);
        } 
    } else if (sourceRecord != null) {
        if (!addingToTask &&
                (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
            // In this case, we are adding the activity to an existing
            // task, but the caller has asked to clear that task if the
            // activity is already running.
            //清除r所在task在r之上的所有task,如果r不在task里,则返回的top为null
            ActivityRecord top = performClearTaskLocked(
                    sourceRecord.task.taskId, r, launchFlags);
            keepCurTransition = true;
            if (top != null) {
                logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
                //先调用onNewIntent方法 然后再显示
                top.deliverNewIntentLocked(callingUid, r.intent);
                // For paranoia, make sure we have correctly
                // resumed the top activity.
                if (doResume) {
                    resumeTopActivityLocked(null);
                }
                ActivityOptions.abort(options);
                return ActivityManager.START_DELIVERED_TO_TOP;
            }
        } else if (!addingToTask &&
                (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
            //将栈里已有的activity移到栈顶
            // In this case, we are launching an activity in our own task
            // that may already be running somewhere in the history, and
            // we want to shuffle it to the front of the stack if so.
            int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
            if (where >= 0) {
                ActivityRecord top = moveActivityToFrontLocked(where);
                logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
                top.updateOptionsLocked(options);
                top.deliverNewIntentLocked(callingUid, r.intent);
                if (doResume) {
                    resumeTopActivityLocked(null);
                }
                return ActivityManager.START_DELIVERED_TO_TOP;
            }
        }
        // An existing activity is starting this new activity, so we want
        // to keep the new one in the same task as the one that is starting
        // it.
        //同一个应用程序里的Activity A和Activity B,A可跳转至B,没有设置taskAffinity
        //B的启动模式为singleTask,从A跳转至B时,B和A会在同一个task里
        //该情况下会执行到这里的代码,将B的task设置为和A一样的task
        r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
        if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
                + " in existing task " + r.task); 
    } else {
        // This not being started from an existing activity, and not part
        // of a new task...  just put it in the top task, though these days
        // this case should never happen.
        final int N = mHistory.size();
        ActivityRecord prev =
            N > 0 ? mHistory.get(N-1) : null;
        r.setTask(prev != null
                ? prev.task
                : new TaskRecord(mService.mCurTask, r.info, intent), null, true);
        if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
                + " in new guessed " + r.task);
    }  
    mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
            intent, r.getUriPermissionsLocked()); 
    if (newTask) {
        EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
    }
    logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
    startActivityLocked(r, newTask, doResume, keepCurTransition, options);
    return ActivityManager.START_SUCCESS;
}

实际场景分析

实际场景1:

应用内有两个Activity,A和B,A为第应用入口Activity,从A可跳转至B,A和B的启动模式都为standard

1)从Launcher程序第1次启动应用时的任务调度情况:

任务调度时会创建新task并将新的ActivityRecord加入这个新的task

2)然后跳转至应用内Activity时的任务调度情况:

任务调度时会将新的ActivityRecord加入已有的task

3)然后按Home键,再打开应用程序时的调度情况:

任务调度时会先找到已有的相关task,并显示栈顶的Activity

1)从Launcher程序第1次启动应用时

会创建新task并将新的ActivityRecord加入这个新的task,任务调度执行如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
final int startActivityUncheckedLocked(ActivityRecord r,
        ActivityRecord sourceRecord, int startFlags, boolean doResume,
        Bundle options) {
    //...
    //launchFlags为FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
    int launchFlags = intent.getFlags();
   //... 
   //没设置FLAG_ACTIVITY_PREVIOUS_IS_TOP,故此notTop为null        
    ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
            != 0 ? r : null;
   //startFlags未设置ActivityManager.START_FLAG_ONLY_IF_NEEDED
   //...  
   //sourceRecord为Launcher应用的Activity  launcher应用activity的启动模式为singleTask
   // 故此下面的3个条件分支的内容都不会执行  
    if (sourceRecord == null) {
        //... 
    } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
         //...
    } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
        //... 
    }
    //... 
    //r.resultTo不为null, launchFlags设置了FLAG_ACTIVITY_NEW_TASK,需要将r.resultTo置为null
    if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
        //... 
        r.resultTo = null;
    }         
    boolean addingToTask = false;
    boolean movedHome = false;
    TaskRecord reuseTask = null;
    //因为launchFlags为FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
    //故此下面的条件会满足, 也就是说只要从Launcher程序启动应用,下面这个条件肯定会满足
    if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
            (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
        //... 
        if (r.resultTo == null) {
            //因为应用被*次启动,故此找不到相关task,taskTop则为null
            ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
                    ? findTaskLocked(intent, r.info)
                    : findActivityLocked(intent, r.info);
            if (taskTop != null) {
              //... 这里面的内容不会执行
            }     
        }
    }
   //...
   //r.packageName != null
    if (r.packageName != null) {
        //如果被启动的Activity正好是栈顶的Activity,
        //并且被启动的Activity启动模式是singleTop或者singleTask,
        //则不用将新的ActivityRecord加入到栈里
        //top Activity为Launcher应用的Activity 
        ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);
        if (top != null && r.resultTo == null) {
            //top.realActivity.equals(r.realActivity)不满足
            if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
                //... 这里的代码不会被执行 
            }
        }

    } else {
        //...
    } 
    boolean newTask = false;
    boolean keepCurTransition = false;
    // 此时 r.resultTo为null addingToTask为false  launchFlags设置了FLAG_ACTIVITY_NEW_TASK
    if (r.resultTo == null && !addingToTask
            && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
        if (reuseTask == null) {
            // todo: should do better management of integers.
            mService.mCurTask++;
            if (mService.mCurTask <= 0) {
                mService.mCurTask = 1;
            }
            //创建新task
            r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null, true);
            if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
                    + " in new task " + r.task);
        } else {
           //...这里的代码会执行
        }
        newTask = true;
        if (!movedHome) {
            moveHomeToFrontFromLaunchLocked(launchFlags);
        }
        
    } else if (sourceRecord != null) {
         //... 这里的代码不会被执行
    } else {
       //...这里的代码不会被执行
    }
    //... 
    startActivityLocked(r, newTask, doResume, keepCurTransition, options);
    return ActivityManager.START_SUCCESS;
}

2)跳转至应用内Activity时

会将新的ActivityRecord加入已有的task,任务调度执行如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
final int startActivityUncheckedLocked(ActivityRecord r,
        ActivityRecord sourceRecord, int startFlags, boolean doResume,
        Bundle options) {
    //此时launchFlags为0 
    int launchFlags = intent.getFlags();
    //notTop为null    
    ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
            != 0 ? r : null;
    //startFlags未设置ActivityManager.START_FLAG_ONLY_IF_NEEDED
    //...     
    if (sourceRecord == null) {
       //...这里的代码不会被执行
    } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
      //...这里的代码不会被执行   
    } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
      //...这里的代码不会被执行     
    }
    //r.resultTo != null 但是launchFlags未设置FLAG_ACTIVITY_NEW_TASK
    if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
       //... 这里的代码不执行  
    }
    boolean addingToTask = false;
    boolean movedHome = false;
    TaskRecord reuseTask = null;
    //launchFlags为0 r的启动模式为standard 故此下面的逻辑都不会执行
    if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
            (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
        //... 这里的代码不执行
    }
   //...
    if (r.packageName != null) {
        //top 是ActivityA 的ActivityRecord,
        //但是被启动的Activity和top不是同一个Activity
        ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);
        if (top != null && r.resultTo == null) {
            if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
                 //...这里的代码不执行
            }
        }

    } else {
        //...这里的代码不执行
    }
    boolean newTask = false;
    boolean keepCurTransition = false;
    //此时 r.resultTo !=null  sourceRecord != null addingToTask=false
    if (r.resultTo == null && !addingToTask
            && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
        //...这里的代码不执行         
    } else if (sourceRecord != null) {
        if (!addingToTask &&
                (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
             //... 这里的代码不执行
        } else if (!addingToTask &&
                (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
             //... 这里的代码不执行 
        }
        //添加到现有的task 
        r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
        //... 
    } else {
        //... 这里的代码不执行 
    }
    //...
    return ActivityManager.START_SUCCESS;
}

3)然后按Home键,再打开应用程序

此时会先找到已有的相关task,并显示栈顶的Activity,任务调度执行如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
final int startActivityUncheckedLocked(ActivityRecord r,
        ActivityRecord sourceRecord, int startFlags, boolean doResume,
        Bundle options) {
    //...
    //launchFlags为FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 
    int launchFlags = intent.getFlags();
    //notTop为null    
    ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
            != 0 ? r : null;
    //startFlags未设置ActivityManager.START_FLAG_ONLY_IF_NEEDED
    //...         
    if (sourceRecord == null) {
       //...这里的代码不会被执行
    } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
        //...这里的代码不会被执行  
    } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
       //...这里的代码不会被执行 
    }
    //此时 r.resultTo != null launchFlags设置了FLAG_ACTIVITY_NEW_TASK
    if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
        //...
        r.resultTo = null;
    } 
    boolean addingToTask = false;
    boolean movedHome = false;
    TaskRecord reuseTask = null;
    //此时launchFlags设置了FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 
    if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
            (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
        //此时 r.resultTo == null
        if (r.resultTo == null) {
            //此时已有相关task,并且task 栈的栈顶是Activity B的ActivityRecord
            //故此taskTop为Activity B的ActivityRecord 
            ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
                    ? findTaskLocked(intent, r.info)
                    : findActivityLocked(intent, r.info);
            if (taskTop != null) {
                //... 
                // 此时curTop是Launcher应用的Activity的ActivityRecord  
                ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop);
                if (curTop != null && curTop.task != taskTop.task) {
                    r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
                    //此时Launcher应用的task在栈顶,故此callerAtFront为true,
                    //此时会把被启动的应用的task移至栈顶
                    boolean callerAtFront = sourceRecord == null
                            || curTop.task == sourceRecord.task;
                    if (callerAtFront) {
                        // We really do want to push this one into the
                        // user's face, right now.
                        movedHome = true;
                        moveHomeToFrontFromLaunchLocked(launchFlags);
                        moveTaskToFrontLocked(taskTop.task, r, options);
                        options = null;
                    }
                }
                //此时launchFlags设置了FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                //此时需要重置task 重置完后 taskTop为ActivityB的ActivityRecord   
                if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
                    taskTop = resetTaskIfNeededLocked(taskTop, r);
                }
                //startFlags为0
                if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED)  != 0) {
                    //... 这些代码都不会被执行 
                } 
                //根据launchFlags和被启动的activity的信息 设置resueTask addingTask变量的值                  
                //没设置 Intent.FLAG_ACTIVITY_CLEAR_TASK
                if ((launchFlags &
                          (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
                          == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
                      //... 这些代码都不会被执行  
                 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
                          || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
                          || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
                      //... 这些代码都不会被执行  
                 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
                      //... 这些代码都不会被执行   
                 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
                       //因为从Launcher程序启动时launchFlags设置了FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                       //所以不会进入该分支
                       //... 这些代码都不会被执行   
                  } else if (!taskTop.task.rootWasReset) {
                       //... 这些代码都不会被执行    
                  }  
                  //此时addingToTask为false,reuseTask为null,故此显示栈顶Actvity即可
                  if (!addingToTask && reuseTask == null) {
                      // We didn't do anything...  but it was needed (a.k.a., client
                      // don't use that intent!)  And for paranoia, make
                      // sure we have correctly resumed the top activity.
                      if (doResume) {
                          resumeTopActivityLocked(null, options);
                      } else {
                          ActivityOptions.abort(options);
                      }
                      return ActivityManager.START_TASK_TO_FRONT;
                  } 
            }
        }
    }
   //... 以下代码都不会被执行    
}

实际场景2:

应用内有两个Activity,A和B,A为第应用入口Activity,从A可跳转至B,A的启动模式都为standard,B的启动模式为singleTop

此时已从Launchenr程序打开应用,启动了Actvity A,再从A跳转至B,此时的任务调度情况:

此时不会创建新的Task,而是将B的ActivityRecord加入到A所在的task里

任务调度执行如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
final int startActivityUncheckedLocked(ActivityRecord r,
        ActivityRecord sourceRecord, int startFlags, boolean doResume,
        Bundle options) {
    //...  
    //此时launcheFlags为0
    int launchFlags = intent.getFlags();      
    //notTop为null
    ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
            != 0 ? r : null;
    //默认情况下startFlags不会设置START_FLAG_ONLY_IF_NEEDED    
    if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
        //...这里的代码不会执行
    }    
    //r.launchMode = ActivityInfo.LAUNCH_SINGLE_TASK 
    if (sourceRecord == null) {
       //这里的代码不会执行  
    } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
        //这里的代码不会执行    
    } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
        launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
    }
    
    //此时r.resultTo!=null launchFlags设置了Intent.FLAG_ACTIVITY_NEW_TASK
    if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
       //...
        r.resultTo = null;
    }       
    //addingToTask如果为true表示正在添加至某个task,后续需要将r添加至sourceRecord所在的task
    boolean addingToTask = false;
    //movedHome表示是否移动home task
    boolean movedHome = false; 
    TaskRecord reuseTask = null;       
    if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
            (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
        //此时 r.resultTo = null
        if (r.resultTo == null) {
            //此时找到的taskTop是Activity A的ActivityRecord,
            //因为Actvity B和A的ActivityRecord所在的Task是相关的
            ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
                    ? findTaskLocked(intent, r.info)
                    : findActivityLocked(intent, r.info);
            //找到了相关task        
            if (taskTop != null) {
                //重设task的intent
                if (taskTop.task.intent == null) {
                     //...
                }
                //此时找到的task已在栈顶
                ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop);
                if (curTop != null && curTop.task != taskTop.task) {
                    //... 这里的代码不会执行 
                }
                //launchFlags为0
                if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
                    taskTop = resetTaskIfNeededLocked(taskTop, r);
                }
                //... 一般情况下startFlags 不会设置 START_FLAG_ONLY_IF_NEEDED
                if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED)  != 0) {
                    //...
                } 
                
                // ==================== begin
                // launchFlags此时为0
                if ((launchFlags &
                        (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
                        == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
                     //...这里的代码不执行
                } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
                        || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
                        || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
                    // r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
                    // 故此会进入该分支
                    //因为B还从未启动,故此得到的top为null
                    ActivityRecord top = performClearTaskLocked(
                            taskTop.task.taskId, r, launchFlags);
                    if (top != null) {
                        //...这里的代码不执行 
                    } else { 
                        addingToTask = true; 
                        sourceRecord = taskTop;
                    }
                } else if (r.realActivity.equals(taskTop.task.realActivity)) {
                     //...这里的代码不执行 
                } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
                     //...这里的代码不执行 
                } else if (!taskTop.task.rootWasReset) {
                     //...这里的代码不执行 
                }
                // ==================== end     
                
                // 此时 addingToTask为true          
                if (!addingToTask && reuseTask == null) {
                     //...这里的代码不执行 
                }
            }
        }
    } 
    //... 

    if (r.packageName != null) { 
        ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);
        if (top != null && r.resultTo == null) {
            //此时task还没有B的ActivityRecord,故此不会进入下述分支
            if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
                 //...这里的代码不执行
            }
        }

    } else {
           //...这里的代码不执行
    }

    boolean newTask = false;
    boolean keepCurTransition = false;

    // 此时 r.resultTo == null addingToTask为true sourceRecord != null
    if (r.resultTo == null && !addingToTask
            && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
         //...这里的代码不执行 
    } else if (sourceRecord != null) {
        if (!addingToTask &&
                (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
               //...这里的代码不执行 
        } else if (!addingToTask &&
                (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
               //...这里的代码不执行 
        }
        //将B的ActivityRecord加入A的ActivityRecord所在的Task里 
        r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
        //... 
    } else {
         //...这里的代码不执行
    }
    //...
    startActivityLocked(r, newTask, doResume, keepCurTransition, options);
    return ActivityManager.START_SUCCESS;
}

总结

从上面的分析可以看出来,Activity和Task的调度算法非常复杂,需结合实际场景才好分析,只有这样才知道是否需要新建Task,还是将新的ActivityRecord加入到已有的Task里,不过我们如果能理解启动模式的一些特点,对理解调度算法会有很大帮助。

大家可以结合下述场景分析调度算法:

1.从通知栏启动Activity:

假设应用有Activity A ,Activity A已启动,

此时发了一个通知,该通知用于启动Activity A,启动Activity A时不加任何特殊flag

点击通知,针对以下情况对任务调度情况进行分析:

1) Activity A的启动模式为standard

2) Activity A的启动模式为singleTop

3) Activity A的启动模式为singleTask

4) Activity A的启动模式为singleInstance

2.跨应用跳转Activity

假设应用app1有一个Activity A,另一个应用app2有一个Activity B

Activity A可跳转至Activity B

因为Activity A和Actiivty B在不同应用,所以Activity的taskffinity必然不同

现在Activity A已启动,跳转至Activity B,

针对以下4种情况分析跳转之后的Activity Task情况

1) Activity B的启动模式为standard

2) Activity B的启动模式为singleTop

3) Activity B的启动模式为singleTask

4) Activity B的启动模式为singleInstance

如果大家对上述场景分析有兴趣的话,可以在评论里一起探讨结果。

Activity启动流程

好吧,终于要开始讲解Activity的启动流程了,Activity的启动流程相对复杂一下,涉及到了Activity中的生命周期方法,涉及到了Android体系的CS模式,涉及到了Android中进程通讯Binder机制等等,

首先介绍一下Activity,这里引用一下Android guide中对Activity的介绍:

An activity represents a single screen with a user interface. For example, an email application might have one activity that shows a list of new emails, another activity to compose an email, and another activity for reading emails. Although the activities work together to form a cohesive user experience in the email application, each one is independent of the others. As such, a different application can start any one of these activities (if the email application allows it). For example, a camera application can start the activity in the email application that composes new mail, in order for the user to share a picture.

英文不太好,这里就不献丑了,这里介绍的Activity的大概意思就是说,activity在Android系统中代表的就是一个屏幕,一个App就是由许多个不同的Acitivty组成的,并且不同进程之间的Activity是可以相互调用的。

在介绍Activity的启动流程之前,我们先介绍几个概念:

  • Activity的生命周期

protected void onCreate(Bundle savedInstanceState);
protected void onRestart();
protected void onStart();
protected void onResume();
protected void onPause();
protected void onStop();
protected void onDestory();
以上为Activity生命周期中的各个时期的回调方法,在不同的方法中我们可以执行不同的逻辑。
关于Activity生命周期的详细介绍可以参考: Android activity的生命周期

  • Activity的启动模式

activity启动时可以设置不同的启动模式,主要是:standrand,singleTop,singleTask,instance等四种启动模式,不同的启动模式在启动Activity时会执行不同的逻辑,系统会按不同的启动模式将Activity存放到不同的activity栈中。
关于Activity启动模式的详细介绍,可以参考: Android任务和返回栈完全解析

  • Activity的启动进程

在Manifest.xml中定义Activity的时候,Activity默认是属于进程名称为包名的进程的,当然这时候是可以指定Activity的启动进程,所以在Activity启动时首先会检测当前Activity所属的进程是否已经启动,若进程没有启动,则首先会启动该进程,并在该进程启动之后才会执行Activity的启动过程。

  • Intent启动Activity的方式

    Intent启动Activity分为两种,显示启动和隐士启动,显示启动就是在初始化Intent对象的时候直接引用需要启动的Activity的字节码,显示引用的好处就是可以直接告诉Intent对象启动的Activity对象不需要执行intent filter索引需要启动哪一个Activity,但是显示引用不能启动其他进程的Activity对象,因为无法获取其他进程的Activity对象的字节码,而隐式启动则可以通过配置Intent Filter启动其他进程的Activity对象,因此在应用内,我们一般都是使用显示启动的方式启动Activity,而如果需要启动其他应用的Activity时,一般使用隐式启动的方式。

  • Android Framework层的CS模式
    通过前几篇文章的介绍我们知道android系统在启动过程中会执行这样的逻辑:
    Zygote进程 –> SystemServer进程 –> 各种系统服务 –> 应用进程
    在Actvity启动过程中,其实是应用进程与SystemServer进程相互配合启动Activity的过程,其中应用进程主要用于执行具体的Activity的启动过程,回调生命周期方法等操作,而SystemServer进程则主要是调用其中的各种服务,将Activity保存在栈中,协调各种系统资源等操作。
  • Android系统进程间通讯Binder机制
    Android系统存了Zygote进程和SystemServer进程以及各种应用进程等,为了能够实现各种进程之间的通讯,Android系统采用了自己的进程间通讯方式Binder机制。其中主要涉及到了四种角色:Binder Client,Binder Server,Binder Manager, Binder driver。各种角色之间的关系可以参考下面这张图的介绍:
    这里写图片描述

好吧,前面我们介绍了一些Activity启动过程中需要的相关知识点,下面我们开始Activity启动流程的讲解。。。。

还记得前面我们讲过的Launcher启动流程么?可以参考:android源码解析之(十)–>Launcher启动流程
在这篇文章中我们说Launcher启动之后会将各个应用包名和icon与app name保存起来,然后执行icon的点击事件的时候调用startActivity方法:

@Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        Intent intent = intentForPosition(position);
        startActivity(intent);
    }

protected Intent intentForPosition(int position) {
        ActivityAdapter adapter = (ActivityAdapter) mAdapter;
        return adapter.intentForPosition(position);
    }

public Intent intentForPosition(int position) {
            if (mActivitiesList == null) {
                return null;
            }

            Intent intent = new Intent(mIntent);
            ListItem item = mActivitiesList.get(position);
            intent.setClassName(item.packageName, item.className);
            if (item.extras != null) {
                intent.putExtras(item.extras);
            }
            return intent;
        }

 

可以发现,我们在启动Activity的时候,执行的逻辑就是创建一个Intent对象,然后初始化Intent对象,使用隐式启动的方式启动该Acvitity,这里为什么不能使用显示启动的方式呢?

这是因为Launcher程序启动的Activity一般都是启动一个新的应用进程,该进程与Launcher进程不是在同一个进程中,所以也就无法引用到启动的Activity字节码,自然也就无法启动该Activity了。

继续,我们查看startActivity方法的具体实现:

一:开始请求执行启动Activity

MyActivity.startActivity()
Activity.startActivity()
Activity.startActivityForResult
Instrumentation.execStartActivty
ActivityManagerNative.getDefault().startActivityAsUser()

在我们的Activity中调用startActivity方法,会执行Activity中的startActivity

@Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }

 

然后在Activity中的startActivity方法体里调用了startActivity的重载方法,这里我们看一下其重载方法的实现:

@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);
        }
    }

 

由于在上一步骤中我们传递的Bunde对象为空,所以这里我们执行的是else分支的逻辑,所以这里调用了startActivityForResult方法,并且传递的参数为intent和-1.

注意:通过这里的代码我们可以发现,其实我们在Activity中调用startActivity的内部也是调用的startActivityForResult的。那么为什么调用startActivityForResult可以在Activity中回调onActivityResult而调用startActivity则不可以呢?可以发现其主要的区别是调用startActivity内部调用startActivityForResult传递的传输requestCode值为-1,也就是说我们在Activity调用startActivityForResult的时候传递的requestCode值为-1的话,那么onActivityResult是不起作用的。
实际上,经测试requestCode的值小于0的时候都是不起作用的,所以当我们调用startActivityForResult的时候需要注意这一点。

好吧,我们继续往下看,startActivityForResult方法的具体实现:

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if (mParent == null) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                // If this start is requesting a result, we can avoid making
                // the activity visible until the result is received.  Setting
                // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                // activity hidden during this time, to avoid flickering.
                // This can only be done when a result is requested because
                // that guarantees we will get information back when the
                // activity is finished, no matter what happens to it.
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

 

可以发现由于我们是*次启动Activity,所以这里的mParent为空,所以会执行if分之,然后调用mInstrumentation.execStartActivity方法,并且这里需要注意的是,有一个判断逻辑:

if (requestCode >= 0) {
    mStartedActivity = true;
}

 

通过注释也验证了我们刚刚的说法即,调用startActivityForResult的时候只有requestCode的值大于等于0,onActivityResult才会被回调。

然后我们看一下mInstrumentation.execStartActivity方法的实现。在查看execStartActivity方法之前,我们需要对mInstrumentation对象有一个了解?什么是Instrumentation?Instrumentation是android系统中启动Activity的一个实际操作类,也就是说Activity在应用进程端的启动实际上就是Instrumentation执行的,那么为什么说是在应用进程端的启动呢?实际上acitivty的启动分为应用进程端的启动和SystemServer服务进程端的启动的,多个应用进程相互配合*终完成了Activity在系统中的启动的,而在应用进程端的启动实际的操作类就是Intrumentation来执行的,可能还是有点绕口,没关系,随着我们慢慢的解析大家就会对Instrumentation的认识逐渐加深的。

可以发现execStartActivity方法传递的几个参数:
this,为启动Activity的对象;
contextThread,为Binder对象,是主进程的context对象;
token,也是一个Binder对象,指向了服务端一个ActivityRecord对象;
target,为启动的Activity;
intent,启动的Intent对象;
requestCode,请求码;
options,参数;

这样就调用了Imstrument.execStartActivity方法了:

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        ...
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), 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;
    }

 

我们发现在这个方法中主要调用ActivityManagerNative.getDefault().startActivity方法,那么ActivityManagerNative又是个什么鬼呢?查看一下getDefault()对象的实现:

static public IActivityManager getDefault() {
        return gDefault.get();
    }

 

好吧,相当之简单直接返回的是gDefault.get(),那么gDefault又是什么呢?

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

 

可以发现启动过asInterface()方法创建,然后我们继续看一下asInterface方法的实现:

static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

 

好吧,*后直接返回一个ActivityManagerProxy对象,而ActivityManagerProxy继承与IActivityManager,到了这里就引出了我们android系统中很重要的一个概念:Binder机制。我们知道应用进程与SystemServer进程属于两个不同的进程,进程之间需要通讯,android系统采取了自身设计的Binder机制,这里的ActivityManagerProxy和ActivityManagerNative都是继承与IActivityManager的而SystemServer进程中的ActivityManagerService对象则继承与ActivityManagerNative。简单的表示:
Binder接口 –> ActivityManagerNative/ActivityManagerProxy –> ActivityManagerService;

这样,ActivityManagerNative与ActivityManagerProxy相当于一个Binder的客户端而ActivityManagerService相当于Binder的服务端,这样当ActivityManagerNative调用接口方法的时候底层通过Binder driver就会将请求数据与请求传递给server端,并在server端执行具体的接口逻辑。需要注意的是Binder机制是单向的,是异步的,也就是说只能通过client端向server端传递数据与请求而不同等待服务端的返回,也无法返回,那如果SystemServer进程想向应用进程传递数据怎么办?这时候就需要重新定义一个Binder请求以SystemServer为client端,以应用进程为server端,这样就是实现了两个进程之间的双向通讯。

好了,说了这么多我们知道这里的ActivityManagerNative是ActivityManagerService在应用进程的一个client就好了,通过它就可以滴啊用ActivityManagerService的方法了。

继续往下卡,我们调用的是:

int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);

 

这里通过我们刚刚的分析,ActivityManagerNative.getDefault()方法会返回一个ActivityManagerProxy对象,那么我们看一下ActivityManagerProxy对象的startActivity方法:

public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(callingPackage);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(startFlags);
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        if (options != null) {
            data.writeInt(1);
            options.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }

 

这里就涉及到了具体的Binder数据传输机制了,我们不做过多的分析,知道通过数据传输之后就会调用SystemServer进程的ActivityManagerService的startActivity就好了。

以上其实都是发生在应用进程中,下面开始调用的ActivityManagerService的执行时发生在SystemServer进程。

二:ActivityManagerService接收启动Activity的请求

ActivityManagerService.startActivity()
ActvityiManagerService.startActivityAsUser()
ActivityStackSupervisor.startActivityMayWait()
ActivityStackSupervisor.startActivityLocked()
ActivityStackSupervisor.startActivityUncheckedLocked()
ActivityStackSupervisor.startActivityLocked()
ActivityStackSupervisor.resumeTopActivitiesLocked()
ActivityStackSupervisor.resumeTopActivityInnerLocked()

好吧,代码量比较大,慢慢看,首先看一下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 options) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, options,
            UserHandle.getCallingUserId());
    }

 

可以看到,该方法并没有实现什么逻辑,直接调用了startActivityAsUser方法,我们继续看一下startActivityAsUser方法的实现:

@Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, false, userId, null, null);
    }

 

可以看到这里只是进行了一些关于userid的逻辑判断,然后就调用mStackSupervisor.startActivityMayWait方法,下面我们来看一下这个方法的具体实现:

final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
            Bundle options, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask) {
            ...

            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage,
                    realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                    componentSpecified, null, container, inTask);
            ...
            return res;
    }

 

这个方法中执行了启动Activity的一些其他逻辑判断,在经过判断逻辑之后调用startActivityLocked方法:

final int startActivityLocked(IApplicationThread caller,
            Intent intent, String resolvedType, ActivityInfo aInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode,
            int callingPid, int callingUid, String callingPackage,
            int realCallingPid, int realCallingUid, int startFlags, Bundle options,
            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
            ActivityContainer container, TaskRecord inTask) {
        int err = ActivityManager.START_SUCCESS;

        ...
        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);

        ...
        return err;
    }

 

这个方法中主要构造了ActivityManagerService端的Activity对象–>ActivityRecord,并根据Activity的启动模式执行了相关逻辑。然后调用了startActivityUncheckedLocked方法:

final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
            boolean doResume, Bundle options, TaskRecord inTask) {
        ...
        ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
        targetStack.mLastPausedActivity = null;
        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
        if (!launchTaskBehind) {
            // Don't set focus on an activity that's going to the back.
            mService.setFocusedActivityLocked(r, "startedActivity");
        }
        return ActivityManager.START_SUCCESS;
    }

 

startActivityUncheckedLocked方法中只要执行了不同启动模式不同栈的处理,并*后调用了startActivityLocked的重载方法:

final void startActivityLocked(ActivityRecord r, boolean newTask,
            boolean doResume, boolean keepCurTransition, Bundle options) {
        ...
        if (doResume) {
            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
        }
    }

 

这个startActivityLocked方法主要执行初始化了windowManager服务,然后调用resumeTopActivitiesLocked方法:

boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
            Bundle targetOptions) {
        if (targetStack == null) {
            targetStack = mFocusedStack;
        }
        // Do targetStack first.
        boolean result = false;
        if (isFrontStack(targetStack)) {
            result = targetStack.resumeTopActivityLocked(target, targetOptions);
        }

        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (stack == targetStack) {
                    // Already started above.
                    continue;
                }
                if (isFrontStack(stack)) {
                    stack.resumeTopActivityLocked(null);
                }
            }
        }
        return result;
    }

 

可以发现经过循环逻辑判断之后,*终调用了resumeTopActivityLocked方法:

final boolean resumeTopActivityLocked(ActivityRecord prev) {
        return resumeTopActivityLocked(prev, null);
    }

 

然后调用:

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
        if (mStackSupervisor.inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
                mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
                mService.updateSleepIfNeededLocked();
            }
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
        return result;
    }

 

继续调用resumeTopActivityInnerLocked方法:

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {

        ...
        if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
        }        ...
        return true;
    }

 

经过一系列处理逻辑之后*终调用了startPausingLocked方法,这个方法作用就是让系统中栈中的Activity执行onPause方法。

三:执行栈顶Activity的onPause方法

ActivityStack.startPausingLocked()
IApplicationThread.schudulePauseActivity()
ActivityThread.sendMessage()
ActivityThread.H.sendMessage();
ActivityThread.H.handleMessage()
ActivityThread.handlePauseActivity()
ActivityThread.performPauseActivity()
Activity.performPause()
Activity.onPause()
ActivityManagerNative.getDefault().activityPaused(token)
ActivityManagerService.activityPaused()
ActivityStack.activityPausedLocked()
ActivityStack.completePauseLocked()
ActivityStack.resumeTopActivitiesLocked()
ActivityStack.resumeTopActivityLocked()
ActivityStack.resumeTopActivityInnerLocked()
ActivityStack.startSpecificActivityLocked

好吧,方法比较多也比较乱,首先来看startPausingLocked方法:

final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
            boolean dontWait) {
        ...
        if (prev.app != null && prev.app.thread != null) {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
            try {
                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                        prev.userId, System.identityHashCode(prev),
                        prev.shortComponentName);
                mService.updateUsageStats(prev, false);
                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                        userLeaving, prev.configChangeFlags, dontWait);
            } catch (Exception e) {
                // Ignore exception, if process died other code will cleanup.
                Slog.w(TAG, "Exception thrown during pause", e);
                mPausingActivity = null;
                mLastPausedActivity = null;
                mLastNoHistoryActivity = null;
            }
        } else {
            mPausingActivity = null;
            mLastPausedActivity = null;
            mLastNoHistoryActivity = null;
        }
        ...
    }

 

可以看到这里执行了pre.app.thread.schedulePauseActivity方法,通过分析不难发现这里的thread是一个IApplicationThread类型的对象,而在ActivityThread中也定义了一个ApplicationThread的类,其继承了IApplicationThread,并且都是Binder对象,不难看出这里的IAppcation是一个Binder的client端而ActivityThread中的ApplicationThread是一个Binder对象的server端,所以通过这里的thread.schedulePauseActivity实际上调用的就是ApplicationThread的schedulePauseActivity方法。

这里的ApplicationThread可以和ActivityManagerNative对于一下:
通过ActivityManagerNative –> ActivityManagerService实现了应用进程与SystemServer进程的通讯
通过AppicationThread <– IApplicationThread实现了SystemServer进程与应用进程的通讯

然后我们继续看一下ActivityThread中schedulePauseActivity的具体实现:

public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges, boolean dontReport) {
            sendMessage(
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? 1 : 0) | (dontReport ? 2 : 0),
                    configChanges);
        }

 

发送了PAUSE_ACTIVITY_FINISHING消息,然后看一下sendMessage的实现方法:

private void sendMessage(int what, Object obj, int arg1, int arg2) {
        sendMessage(what, obj, arg1, arg2, false);
    }

 

调用了其重载方法:

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

 

*终调用了mH的sendMessage方法,mH是在ActivityThread中定义的一个Handler对象,主要处理SystemServer进程的消息,我们看一下其handleMessge方法的实现:

public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                ...
                case PAUSE_ACTIVITY_FINISHING:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    handlePauseActivity((IBinder)msg.obj, true, (msg.arg1&1) != 0, msg.arg2,
                            (msg.arg1&1) != 0);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                ...
}

 

可以发现其调用了handlePauseActivity方法:

private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport) {
        ActivityClientRecord r = mActivities.get(token);
        if (r != null) {
            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
            if (userLeaving) {
                performUserLeavingActivity(r);
            }

            r.activity.mConfigChangeFlags |= configChanges;
            performPauseActivity(token, finished, r.isPreHoneycomb());

            // Make sure any pending writes are now committed.
            if (r.isPreHoneycomb()) {
                QueuedWork.waitToFinish();
            }

            // Tell the activity manager we have paused.
            if (!dontReport) {
                try {
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                }
            }
            mSomeActivitiesChanged = true;
        }
    }

 

然后在方法体内部通过调用performPauseActivity方法来实现对栈顶Activity的onPause生命周期方法的回调,可以具体看一下他的实现:

final Bundle performPauseActivity(IBinder token, boolean finished,
            boolean saveState) {
        ActivityClientRecord r = mActivities.get(token);
        return r != null ? performPauseActivity(r, finished, saveState) : null;
    }

 

然后调用其重载方法:

final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState) {
        ...
        mInstrumentation.callActivityOnPause(r.activity);
        ...

        return !r.activity.mFinished && saveState ? r.state : null;
    }

 

这样回到了mInstrumentation的callActivityOnPuase方法:

public void callActivityOnPause(Activity activity) {
        activity.performPause();
    }

 

呵呵,原来*终回调到了Activity的performPause方法:

final void performPause() {
        mDoReportFullyDrawn = false;
        mFragments.dispatchPause();
        mCalled = false;
        onPause();
        mResumed = false;
        if (!mCalled && getApplicationInfo().targetSdkVersion
                >= android.os.Build.VERSION_CODES.GINGERBREAD) {
            throw new SuperNotCalledException(
                    "Activity " + mComponent.toShortString() +
                    " did not call through to super.onPause()");
        }
        mResumed = false;
    }

 

终于,太不容易了,回调到了Activity的onPause方法,哈哈,Activity生命周期中的*个生命周期方法终于被我们找到了。。。。也就是说我们在启动一个Activity的时候*先被执行的是栈顶的Activity的onPause方法。记住这点吧,面试的时候经常会问到类似的问题。

然后回到我们的handlePauseActivity方法,在该方法的*后面执行了ActivityManagerNative.getDefault().activityPaused(token);方法,这是应用进程告诉服务进程,栈顶Activity已经执行完成onPause方法了,通过前面我们的分析,我们知道这句话*终会被ActivityManagerService的activityPaused方法执行。

@Override
    public final void activityPaused(IBinder token) {
        final long origId = Binder.clearCallingIdentity();
        synchronized(this) {
            ActivityStack stack = ActivityRecord.getStackLocked(token);
            if (stack != null) {
                stack.activityPausedLocked(token, false);
            }
        }
        Binder.restoreCallingIdentity(origId);
    }

 

可以发现,该方法内部会调用ActivityStack的activityPausedLocked方法,好吧,继续看一下activityPausedLocked方法的实现:

final void activityPausedLocked(IBinder token, boolean timeout) {
            ...
                if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
                        + (timeout ? " (due to timeout)" : " (pause complete)"));
                completePauseLocked(true);
            ...
    }

 

然后执行了completePauseLocked方法:

private void completePauseLocked(boolean resumeNext) {
        ...

        if (resumeNext) {
            final ActivityStack topStack = mStackSupervisor.getFocusedStack();
            if (!mService.isSleepingOrShuttingDown()) {
                mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);
            } else {
                mStackSupervisor.checkReadyForSleepLocked();
                ActivityRecord top = topStack.topRunningActivityLocked(null);
                if (top == null || (prev != null && top != prev)) {
                    // If there are no more activities available to run,
                    // do resume anyway to start something.  Also if the top
                    // activity on the stack is not the just paused activity,
                    // we need to go ahead and resume it to ensure we complete
                    // an in-flight app switch.
                    mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null);
                }
            }
        }
        ...
    }

 

经过了一系列的逻辑之后,又调用了resumeTopActivitiesLocked方法,又回到了第二步中解析的方法中了,这样经过
resumeTopActivitiesLocked –>
ActivityStack.resumeTopActivityLocked() –>
resumeTopActivityInnerLocked –>
startSpecificActivityLocked
好吧,我们看一下startSpecificActivityLocked的具体实现:

void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.task.stack.setLaunchTime(r);

        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    // Don't add this if it is a platform component that is marked
                    // to run in multiple processes, because this is actually
                    // part of the framework so doesn't make sense to track as a
                    // separate apk in the process.
                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }

            // If a dead object exception was thrown -- fall through to
            // restart the application.
        }

        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

 

可以发现在这个方法中,首先会判断一下需要启动的Activity所需要的应用进程是否已经启动,若启动的话,则直接调用realStartAtivityLocked方法,否则调用startProcessLocked方法,用于启动应用进程。
这样关于启动Activity时的第三步骤就已经执行完成了,这里主要是实现了对栈顶Activity执行onPause
方法,而这个方法首先判断需要启动的Activity所属的进程是否已经启动,若已经启动则直接调用启动Activity的方法,否则将先启动Activity的应用进程,然后在启动该Activity。

四:启动Activity所属的应用进程

关于如何启动应用进程,前面的一篇文章已经做了介绍,可参考: android源码解析之(十一)–>应用进程启动流程 这里在简单的介绍一下

ActivityManagerService.startProcessLocked()
Process.start()
ActivityThread.main()
ActivityThread.attach()
ActivityManagerNative.getDefault().attachApplication()
ActivityManagerService.attachApplication()

好吧,首先看一下startProcessLocked()方法的具体实现:

private final void startProcessLocked(ProcessRecord app,
            String hostingType, String hostingNameStr) {
        startProcessLocked(app, hostingType, hostingNameStr, null /* abiOverride */,
                null /* entryPoint */, null /* entryPointArgs */);
    }

 

然后回调了其重载的startProcessLocked方法:

private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
            ...
            boolean isActivityProcess = (entryPoint == null);
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                    app.processName);
            checkTime(startTime, "startProcess: asking zygote to start proc");
            Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);
            checkTime(startTime, "startProcess: returned from zygote!");
            ...
    }

 

可以发现其经过一系列的初始化操作之后调用了Process.start方法,并且传入了启动的类名“android.app.ActivityThread”:

public static final ProcessStartResult start(final String processClass,
                                  final String niceName,
                                  int uid, int gid, int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String[] zygoteArgs) {
        try {
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    debugFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
            Log.e(LOG_TAG,
                    "Starting VM process through Zygote failed");
            throw new RuntimeException(
                    "Starting VM process through Zygote failed", ex);
        }
    }

 

然后调用了startViaZygote方法:

private static ProcessStartResult startViaZygote(final String processClass,
                                  final String niceName,
                                  final int uid, final int gid,
                                  final int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String[] extraArgs)
                                  throws ZygoteStartFailedEx {
        synchronized(Process.class) {
            ...

            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
        }
    }

 

继续查看一下zygoteSendArgsAndGetResult方法的实现:

private static ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, ArrayList<String> args)
            throws ZygoteStartFailedEx {
        try {
            /**
             * See com.android.internal.os.ZygoteInit.readArgumentList()
             * Presently the wire format to the zygote process is:
             * a) a count of arguments (argc, in essence)
             * b) a number of newline-separated argument strings equal to count
             *
             * After the zygote process reads these it will write the pid of
             * the child or -1 on failure, followed by boolean to
             * indicate whether a wrapper process was used.
             */
            final BufferedWriter writer = zygoteState.writer;
            final DataInputStream inputStream = zygoteState.inputStream;

            writer.write(Integer.toString(args.size()));
            writer.newLine();

            int sz = args.size();
            for (int i = 0; i < sz; i++) {
                String arg = args.get(i);
                if (arg.indexOf('\n') >= 0) {
                    throw new ZygoteStartFailedEx(
                            "embedded newlines not allowed");
                }
                writer.write(arg);
                writer.newLine();
            }

            writer.flush();

            // Should there be a timeout on this?
            ProcessStartResult result = new ProcessStartResult();
            result.pid = inputStream.readInt();
            if (result.pid < 0) {
                throw new ZygoteStartFailedEx("fork() failed");
            }
            result.usingWrapper = inputStream.readBoolean();
            return result;
        } catch (IOException ex) {
            zygoteState.close();
            throw new ZygoteStartFailedEx(ex);
        }
    }

 

可以发现其*终调用了Zygote并通过socket通信的方式让Zygote进程fork除了一个新的进程,并根据我们刚刚传递的”android.app.ActivityThread”字符串,反射出该对象并执行ActivityThread的main方法。这样我们所要启动的应用进程这时候其实已经启动了,但是还没有执行相应的初始化操作。

为什么我们平时都将ActivityThread称之为ui线程或者是主线程,这里可以看出,应用进程被创建之后首先执行的是ActivityThread的main方法,所以我们将ActivityThread成为主线程。

好了,这时候我们看一下ActivityThread的main方法的实现逻辑。

public static void main(String[] args) {
        ...
        Process.setArgV0("<pre-initialized>");

        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

 

在main方法中主要执行了一些初始化的逻辑,并且创建了一个UI线程消息队列,这也就是为什么我们可以在主线程中随意的创建Handler而不会报错的原因,这里提出一个问题,大家可以思考一下:子线程可以创建Handler么?可以的话应该怎么做?
然后执行了ActivityThread的attach方法,这里我们看一下attach方法执行了那些逻辑操作。

private void attach(boolean system) {
    ...
    final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
    ...
}

 

刚刚我们已经分析过ActivityManagerNative是ActivityManagerService的Binder client,所以这里调用了attachApplication实际上就是通过Binder机制调用了ActivityManagerService的attachApplication,具体调用的过程,我们看一下ActivityManagerService是如何实现的:

@Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

 

可以发现其回调了attachApplicationLocked方法,我们看一下这个方法的实现逻辑。

private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {

        ...
        // See if the top visible activity is waiting to run in this process...
        if (normalMode) {
            try {
                if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }
        ...

        return true;
    }

 

该方法执行了一系列的初始化操作,这样我们整个应用进程已经启动起来了。终于可以开始activity的启动逻辑了,O(∩_∩)O哈哈~

五:执行启动Acitivity

ActivityStackSupervisor.attachApplicationLocked()
ActivityStackSupervisor.realStartActivityLocked()
IApplicationThread.scheduleLauncherActivity()
ActivityThread.sendMessage()
ActivityThread.H.sendMessage()
ActivityThread.H.handleMessage()
ActivityThread.handleLauncherActivity()
ActivityThread.performLauncherActivity()
Instrumentation.callActivityOnCreate()
Activity.onCreate()
ActivityThread.handleResumeActivity()
ActivityThread.performResumeActivity()
Activity.performResume()
Instrumentation.callActivityOnResume()
Activity.onResume()
ActivityManagerNative.getDefault().activityResumed(token)

首先看一下attachApplicationLocked方法的实现:

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
        final String processName = app.processName;
        boolean didSomething = false;
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (!isFrontStack(stack)) {
                    continue;
                }
                ActivityRecord hr = stack.topRunningActivityLocked(null);
                if (hr != null) {
                    if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                            && processName.equals(hr.processName)) {
                        try {
                            if (realStartActivityLocked(hr, app, true, true)) {
                                didSomething = true;
                            }
                        } catch (RemoteException e) {
                            Slog.w(TAG, "Exception in new application when starting activity "
                                  + hr.intent.getComponent().flattenToShortString(), e);
                            throw e;
                        }
                    }
                }
            }
        }
        if (!didSomething) {
            ensureActivitiesVisibleLocked(null, 0);
        }
        return didSomething;
    }

 

可以发现其内部调用了realStartActivityLocked方法,通过名字可以知道这个方法应该就是用来启动Activity的,看一下这个方法的实现逻辑:

final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {

        ...
            app.forceProcessStateUpTo(mService.mTopProcessState);
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
                    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
        ...
        return true;
    }

 

可以发现与第三步执行栈顶Activity onPause时类似,这里也是通过调用IApplicationThread的方法实现的,这里调用的是scheduleLauncherActivity方法,所以真正执行的是ActivityThread中的scheduleLauncherActivity,所以我们看一下ActivityThread中的scheduleLauncherActivity的实现:

@Override
        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            r.persistentState = persistentState;

            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;

            r.startsNotResumed = notResumed;
            r.isForward = isForward;

            r.profilerInfo = profilerInfo;

            r.overrideConfig = overrideConfig;
            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

 

好吧,还是那套逻辑,ActivityThread接收到SystemServer进程的消息之后会通过其内部的Handler对象分发消息,经过一系列的分发之后调用了ActivityThread的handleLaunchActivity方法:

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {

        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);


        }
        ...
    }

 

可以发现这里调用了performLauncherActivity,看名字应该就是执行Activity的启动操作了。。。

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...

Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }
        ...

        activity.mCalled = false;
        if (r.isPersistable()) {
           mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
        } else {
           mInstrumentation.callActivityOnCreate(activity, r.state);
        }
        ...
        if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }
        ...
        return activity;
    }

 

可以发现这里我们需要的Activity对象终于是创建出来了,而且他是以反射的机制创建的,现在还不太清楚为啥google要以反射的方式创建Activity,先不看这些,然后在代码中其调用Instrumentation的callActivityOnCreate方法。

public void callActivityOnCreate(Activity activity, Bundle icicle,
            PersistableBundle persistentState) {
        prePerformCreate(activity);
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }

 

然后执行activity的performCreate方法。。。。好吧,都转晕了。。。

final void performCreate(Bundle icicle) {
        onCreate(icicle);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }

 

O(∩_∩)O哈哈~,第二个生命周期方法出来了,onCreate方法。。。。

在回到我们的performLaunchActivity方法,其在调用了mInstrumentation.callActivityOnCreate方法之后又调用了activity.performStart();方法,好吧,看一下他的实现方式:

final void performStart() {
        mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
        mFragments.noteStateNotSaved();
        mCalled = false;
        mFragments.execPendingActions();
        mInstrumentation.callActivityOnStart(this);
        if (!mCalled) {
            throw new SuperNotCalledException(
                "Activity " + mComponent.toShortString() +
                " did not call through to super.onStart()");
        }
        mFragments.dispatchStart();
        mFragments.reportLoaderStart();
        mActivityTransitionState.enterReady(this);
    }

 

好吧,还是通过Instrumentation调用callActivityOnStart方法:

public void callActivityOnStart(Activity activity) {
        activity.onStart();
    }

 

然后是直接调用activity的onStart方法,第三个生命周期方法出现了,O(∩_∩)O哈哈~

还是回到我们刚刚的handleLaunchActivity方法,在调用完performLaunchActivity方法之后,其有吊用了handleResumeActivity方法,好吧,看名字应该是回调Activity的onResume方法的。

final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        // TODO Push resumeArgs into the activity for consideration
        ActivityClientRecord r = performResumeActivity(token, clearHide);

        if (r != null) {
            final Activity a = r.activity;

            if (localLOGV) Slog.v(
                TAG, "Resume " + r + " started activity: " +
                a.mStartedActivity + ", hideForNow: " + r.hideForNow
                + ", finished: " + a.mFinished);

            final int forwardBit = isForward ?
                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;

            // If the window hasn't yet been added to the window manager,
            // and this guy didn't finish itself or start another activity,
            // then go ahead and add the window.
            boolean willBeVisible = !a.mStartedActivity;
            if (!willBeVisible) {
                try {
                    willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
                            a.getActivityToken());
                } catch (RemoteException e) {
                }
            }
            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                }

            // If the window has already been added, but during resume
            // we started another activity, then don't yet make the
            // window visible.
            } else if (!willBeVisible) {
                if (localLOGV) Slog.v(
                    TAG, "Launch " + r + " mStartedActivity set");
                r.hideForNow = true;
            }

            // Get rid of anything left hanging around.
            cleanUpPendingRemoveWindows(r);

            // The window is now visible if it has been added, we are not
            // simply finishing, and we are not starting another activity.
            if (!r.activity.mFinished && willBeVisible
                    && r.activity.mDecor != null && !r.hideForNow) {
                if (r.newConfig != null) {
                    r.tmpConfig.setTo(r.newConfig);
                    if (r.overrideConfig != null) {
                        r.tmpConfig.updateFrom(r.overrideConfig);
                    }
                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
                            + r.activityInfo.name + " with newConfig " + r.tmpConfig);
                    performConfigurationChanged(r.activity, r.tmpConfig);
                    freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
                    r.newConfig = null;
                }
                if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
                        + isForward);
                WindowManager.LayoutParams l = r.window.getAttributes();
                if ((l.softInputMode
                        & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
                        != forwardBit) {
                    l.softInputMode = (l.softInputMode
                            & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
                            | forwardBit;
                    if (r.activity.mVisibleFromClient) {
                        ViewManager wm = a.getWindowManager();
                        View decor = r.window.getDecorView();
                        wm.updateViewLayout(decor, l);
                    }
                }
                r.activity.mVisibleFromServer = true;
                mNumVisibleActivities++;
                if (r.activity.mVisibleFromClient) {
                    r.activity.makeVisible();
                }
            }

            if (!r.onlyLocalRequest) {
                r.nextIdle = mNewActivities;
                mNewActivities = r;
                if (localLOGV) Slog.v(
                    TAG, "Scheduling idle handler for " + r);
                Looper.myQueue().addIdleHandler(new Idler());
            }
            r.onlyLocalRequest = false;

            // Tell the activity manager we have resumed.
            if (reallyResume) {
                try {
                    ActivityManagerNative.getDefault().activityResumed(token);
                } catch (RemoteException ex) {
                }
            }

        } else {
            // If an exception was thrown when trying to resume, then
            // just end this activity.
            try {
                ActivityManagerNative.getDefault()
                    .finishActivity(token, Activity.RESULT_CANCELED, null, false);
            } catch (RemoteException ex) {
            }
        }
    }

 

可以发现其resumeActivity的逻辑调用到了performResumeActivity方法,我们来看一下performResumeActivity是如何实现的。

public final ActivityClientRecord performResumeActivity(IBinder token,
            boolean clearHide) {
        ActivityClientRecord r = mActivities.get(token);
        if (localLOGV) Slog.v(TAG, "Performing resume of " + r
                + " finished=" + r.activity.mFinished);
        if (r != null && !r.activity.mFinished) {
            if (clearHide) {
                r.hideForNow = false;
                r.activity.mStartedActivity = false;
            }
            try {
                r.activity.onStateNotSaved();
                r.activity.mFragments.noteStateNotSaved();
                if (r.pendingIntents != null) {
                    deliverNewIntents(r, r.pendingIntents);
                    r.pendingIntents = null;
                }
                if (r.pendingResults != null) {
                    deliverResults(r, r.pendingResults);
                    r.pendingResults = null;
                }
                r.activity.performResume();

                EventLog.writeEvent(LOG_AM_ON_RESUME_CALLED,
                        UserHandle.myUserId(), r.activity.getComponentName().getClassName());

                r.paused = false;
                r.stopped = false;
                r.state = null;
                r.persistentState = null;
            } catch (Exception e) {
                if (!mInstrumentation.onException(r.activity, e)) {
                    throw new RuntimeException(
                        "Unable to resume activity "
                        + r.intent.getComponent().toShortString()
                        + ": " + e.toString(), e);
                }
            }
        }
        return r;
    }

 

在方法体中,*终调用了r.activity.performResume();方法,好吧,这个方法是Activity中定义的方法,我们需要在Activity中查看这个方法的具体实现:

final void performResume() {
        ...
        mInstrumentation.callActivityOnResume(this);
        ...
    }

 

好吧,又是熟悉的味道,通过Instrumentation来调用了callActivityOnResume方法。。。

public void callActivityOnResume(Activity activity) {
        activity.mResumed = true;
        activity.onResume();

        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    am.match(activity, activity, activity.getIntent());
                }
            }
        }
    }

 

O(∩_∩)O哈哈~,第四个生命周期方法出现了,onResume方法。。。

终于回调onResume方法了,这时候我们的界面应该已经展示出来了,照理来说我们的Activity应该已经启动完成了,但是还没有,哈哈,别着急。

有一个问题,Activity a 启动 Activity b 会触发那些生命周期方法?
你可能会回答?b的onCreate onStart方法,onResume方法 a的onPause方法和onStop方法,咦?对了onStop方法还没回调呢,O(∩_∩)O哈哈~,对了缺少的就是对onStop方法的回调啊。

好吧,具体的逻辑我们下一步再说

六:栈顶Activity执行onStop方法

Looper.myQueue().addIdleHandler(new Idler())
Idler.queueIdle()
ActivityManagerNative.getDefault().activityIdle()
ActivityManagerService.activityIdle()
ActivityStackSupervisor.activityIdleInternalLocked()
ActivityStack.stopActivityLocked()
IApplicationThread.scheduleStopActivity()
ActivityThread.scheduleStopActivity()
ActivityThread.sendMessage()
ActivityThread.H.sendMessage()
ActivityThread.H.handleMessage()
ActivityThread.handleStopActivity()
ActivityThread.performStopActivityInner()
ActivityThread.callCallActivityOnSaveInstanceState()
Instrumentation.callActivityOnSaveInstanceState()
Activity.performSaveInstanceState()
Activity.onSaveInstanceState()
Activity.performStop()
Instrumentation.callActivityOnStop()
Activity.onStop()

回到我们的handleResumeActivity方法,在方法体*后有这样的一代码:

Looper.myQueue().addIdleHandler(new Idler());

这段代码是异步消息机制相关的代码,我们可以看一下Idler对象的具体实现:
private class Idler implements MessageQueue.IdleHandler {
        @Override
        public final boolean queueIdle() {
            ActivityClientRecord a = mNewActivities;
            boolean stopProfiling = false;
            if (mBoundApplication != null && mProfiler.profileFd != null
                    && mProfiler.autoStopProfiler) {
                stopProfiling = true;
            }
            if (a != null) {
                mNewActivities = null;
                IActivityManager am = ActivityManagerNative.getDefault();
                ActivityClientRecord prev;
                do {
                    if (localLOGV) Slog.v(
                        TAG, "Reporting idle of " + a +
                        " finished=" +
                        (a.activity != null && a.activity.mFinished));
                    if (a.activity != null && !a.activity.mFinished) {
                        try {
                            am.activityIdle(a.token, a.createdConfig, stopProfiling);
                            a.createdConfig = null;
                        } catch (RemoteException ex) {
                            // Ignore
                        }
                    }
                    prev = a;
                    a = a.nextIdle;
                    prev.nextIdle = null;
                } while (a != null);
            }
            if (stopProfiling) {
                mProfiler.stopProfiling();
            }
            ensureJitEnabled();
            return false;
        }
    }

 

这样当Messagequeue执行add方法之后就会回调其queueIdle()方法,我们可以看到在方法体中其调用了ActivityManagerNative.getDefault().activityIdle(),好吧,熟悉了Binder机制以后我们知道这段代码会执行到ActivityManagerService的activityIdle方法:

@Override
    public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
        final long origId = Binder.clearCallingIdentity();
        synchronized (this) {
            ActivityStack stack = ActivityRecord.getStackLocked(token);
            if (stack != null) {
                ActivityRecord r =
                        mStackSupervisor.activityIdleInternalLocked(token, false, config);
                if (stopProfiling) {
                    if ((mProfileProc == r.app) && (mProfileFd != null)) {
                        try {
                            mProfileFd.close();
                        } catch (IOException e) {
                        }
                        clearProfilerLocked();
                    }
                }
            }
        }
        Binder.restoreCallingIdentity(origId);
    }

 

然后在activityIdle方法中又调用了ActivityStackSupervisor.activityIdleInternalLocked方法:

final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
            Configuration config) {
        ...

        // Stop any activities that are scheduled to do so but have been
        // waiting for the next one to start.
        for (int i = 0; i < NS; i++) {
            r = stops.get(i);
            final ActivityStack stack = r.task.stack;
            if (stack != null) {
                if (r.finishing) {
                    stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
                } else {
                    stack.stopActivityLocked(r);
                }
            }
        }

        ...

        return r;
    }

 

可以发现在其中又调用了ActivityStack.stopActivityLocked方法:

final void stopActivityLocked(ActivityRecord r) {
        if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + r);
        if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
                || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
            ...
                r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
             ...
        }
    }

好吧,又是相同的逻辑通过IApplicationThread.scheduleStopActivity,*终调用了ActivityThread.scheduleStopActivity()方法。。。。
public final void scheduleStopActivity(IBinder token, boolean showWindow,
                int configChanges) {
           sendMessage(
                showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
                token, 0, configChanges);
        }

然后执行sendMessage方法,*终执行H(Handler)的sendMessage方法,并被H的handleMessge方法接收执行handleStopActivity方法。。。
private void handleStopActivity(IBinder token, boolean show, int configChanges) {
        ...
        performStopActivityInner(r, info, show, true);
        ...
    }

然后我们看一下performStopActivityInner的实现逻辑:
private void performStopActivityInner(ActivityClientRecord r,
            StopInfo info, boolean keepShown, boolean saveState) {
            ...
            // Next have the activity save its current state and managed dialogs...
            if (!r.activity.mFinished && saveState) {
                if (r.state == null) {
                    callCallActivityOnSaveInstanceState(r);
                }
            }

            if (!keepShown) {
                try {
                    // Now we are idle.
                    r.activity.performStop();
                } catch (Exception e) {
                    if (!mInstrumentation.onException(r.activity, e)) {
                        throw new RuntimeException(
                                "Unable to stop activity "
                                + r.intent.getComponent().toShortString()
                                + ": " + e.toString(), e);
                    }
                }
                r.stopped = true;
            }
        }
    }

好吧,看样子在这个方法中执行了两个逻辑,一个是执行Activity的onSaveInstance方法一个是执行Activity的onStop方法,我们先看一下callCallActivityOnSaveInstanceState的执行逻辑:

private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) {
        r.state = new Bundle();
        r.state.setAllowFds(false);
        if (r.isPersistable()) {
            r.persistentState = new PersistableBundle();
            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state,
                    r.persistentState);
        } else {
            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
        }
    }

好吧,又是通过Instrumentation来执行。。。

public void callActivityOnSaveInstanceState(Activity activity, Bundle outState,
            PersistableBundle outPersistentState) {
        activity.performSaveInstanceState(outState, outPersistentState);
    }

又间接调用了Activity的performSaveInstanceState方法:
final void performSaveInstanceState(Bundle outState) {
        onSaveInstanceState(outState);
        saveManagedDialogs(outState);
        mActivityTransitionState.saveState(outState);
        if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState);
    }

呵呵,这里调用到了,我们以前经常会重写的onSaveInstanceState方法。

然后我们看一下performStopActivityInner中调用到的Activity方法的performStop方法:

final void performStop() {
        mDoReportFullyDrawn = false;
        mFragments.doLoaderStop(mChangingConfigurations /*retain*/);

        if (!mStopped) {
            if (mWindow != null) {
                mWindow.closeAllPanels();
            }

            if (mToken != null && mParent == null) {
                WindowManagerGlobal.getInstance().setStoppedState(mToken, true);
            }

            mFragments.dispatchStop();

            mCalled = false;
            mInstrumentation.callActivityOnStop(this);
            if (!mCalled) {
                throw new SuperNotCalledException(
                    "Activity " + mComponent.toShortString() +
                    " did not call through to super.onStop()");
            }

            synchronized (mManagedCursors) {
                final int N = mManagedCursors.size();
                for (int i=0; i<N; i++) {
                    ManagedCursor mc = mManagedCursors.get(i);
                    if (!mc.mReleased) {
                        mc.mCursor.deactivate();
                        mc.mReleased = true;
                    }
                }
            }

            mStopped = true;
        }
        mResumed = false;
    }

 

还是通过Instrumentation来实现的,调用了它的callActivityOnStop方法。。

public void callActivityOnStop(Activity activity) {
        activity.onStop();
    }

O(∩_∩)O哈哈~,*后一个生命周期方法终于出来了,onStop()…..

总结:

  • Activity的启动流程一般是通过调用startActivity或者是startActivityForResult来开始的
  • startActivity内部也是通过调用startActivityForResult来启动Activity,只不过传递的requestCode小于0
  • Activity的启动流程涉及到多个进程之间的通讯这里主要是ActivityThread与ActivityManagerService之间的通讯
  • ActivityThread向ActivityManagerService传递进程间消息通过ActivityManagerNative,ActivityManagerService向ActivityThread进程间传递消息通过IApplicationThread。
  • ActivityManagerService接收到应用进程创建Activity的请求之后会执行初始化操作,解析启动模式,保存请求信息等一系列操作。
  • ActivityManagerService保存完请求信息之后会将当前系统栈顶的Activity执行onPause操作,并且IApplication进程间通讯告诉应用程序继承执行当前栈顶的Activity的onPause方法;
  • ActivityThread接收到SystemServer的消息之后会统一交个自身定义的Handler对象处理分发;
  • ActivityThread执行完栈顶的Activity的onPause方法之后会通过ActivityManagerNative执行进程间通讯告诉ActivityManagerService,栈顶Actiity已经执行完成onPause方法,继续执行后续操作;
  • ActivityManagerService会继续执行启动Activity的逻辑,这时候会判断需要启动的Activity所属的应用进程是否已经启动,若没有启动则首先会启动这个Activity的应用程序进程;
  • ActivityManagerService会通过socket与Zygote继承通讯,并告知Zygote进程fork出一个新的应用程序进程,然后执行ActivityThread的mani方法;
  • 在ActivityThead.main方法中执行初始化操作,初始化主线程异步消息,然后通知ActivityManagerService执行进程初始化操作;
  • ActivityManagerService会在执行初始化操作的同时检测当前进程是否有需要创建的Activity对象,若有的话,则执行创建操作;
  • ActivityManagerService将执行创建Activity的通知告知ActivityThread,然后通过反射机制创建出Activity对象,并执行Activity的onCreate方法,onStart方法,onResume方法;
  • ActivityThread执行完成onResume方法之后告知ActivityManagerService onResume执行完成,开始执行栈顶Activity的onStop方法;
  • ActivityManagerService开始执行栈顶的onStop方法并告知ActivityThread;
  • ActivityThread执行真正的onStop方法;

企业如何选择适合自己的服务器呢?

阿里云企业服务器配置选择,和网站或应用的类型、访问量、数据量大小、程序质量等因素息息相关。目前无论个人站长还是企业,都将阿里云作为了上云首选,那么作为企业用户应该如何选择阿里云服务器呢?购买什么配置的阿里云服务器是适合自己的呢?下面我们就来说说企业如何选择阿里云服务器配置:

阿里云个人购买+阿里云企业购买

*步:地域选择

当前阿里云可供我们国内选择的区域有:华北1(青岛),华北2(北京),华北3(张家口),华北5(呼和浩特),华东1(杭州),华东2(上海),华南1(深圳)。海外地域有:香港,亚太东南1(新加坡),亚太东南2(悉尼),亚太东南3(吉隆坡),亚太东南5(雅加达)等。
%title插图%num

建议离目标客户越近越好,例如目标客户多为南方客户,那一般选择华东和华南的服务器比较好,如果目标客户为北京,那建议选择华北比较好。当然,如果预算足够,我们还可以考虑购买阿里云CDN网站加速类产品,这样全国性打开速度都会比较快。

第二步:实例规格选择

目前阿里云可供选择的实例规格有:通用型,计算型,内存型,大数据型,高频型,入门级共享等,这个是很多企业用户*难选的,因为阿里云实例规格众多,很多企业客户看了都不知道怎么选择,其实阿里云已经根据应用场景给我们推荐了对应的型号,只是很多用户没注意到而已:

%title插图%num

例如我们网站只是一个普通企业网站,性能比较均衡的,那我们就可以选择通用型,通用网络增强型即可。普通网站我们推荐一般选择个2核4G或8G以上配置就足够了。

第三步:操作系统
这个很简单,我们只需要根据自己网站的程序选择对应的系统即可,例如网站程序是asp,asp.net开发的,那一般选择windows的系统即可,如果是php语言开发的,那一般选择Centos系统,当然,我们也可以选择镜像市场,选择已经配置好的镜像,这样就省去我们装服务器环境的时间。

第四步:选择硬盘
建议硬盘一定要买一块,价格不贵,如果没有硬盘,那么服务器只有系统盘,如果系统一旦出故障,我们很难找回数据,无论个人还是企业大多数都是将自己网站部署在D盘,而非系统盘,一般企业网站买个50-100G基本上就足够了,重点是硬盘价格不贵,多买点总没坏处。

第五步:选择带宽

一般网站访问量不是很大的,例如日均*多只有两三百人的,一般选择个3M左右带宽就足够了,这里重点说下,假如我们网站在每天特殊事件段访问量会很高,我们可以选择按量付费,这样我们网站就不会出现因为带宽不足而导致网站访问故障了,另外,有些网站会集中在某几天,或者某几周访问量爆发式增长的情况,一般多为网站做推广或者企业做活动之类的时候,那么后期我们可以给服务器增加临时带宽,这样可以节约我们成本,不过无论是按量付费还是增加临时带宽,一定要记得我们账户要随时有钱。

新手如何选择阿里云服务器配置-云惠网

第六步:服务器安全组设置

购买阿里云服务器的时候,安全组可以购买的时候直接设置好,也可以购买之后再设置(包括服务器远程链接密码),这里就不细说了,建议参考阿里云官网的安全组设置帮助设置就好了。

第七步:配置都选择好了,之后我们只需要点击确认下单购买即可,这样我们购买服务器的操作就都走完了。

*后:阿里云还配套了许多其他产品,例如给网站加速的CDN产品,保护网站安全的云盾类产品,用户只需要根据自己的需求和预算选择是否购买即可。点击购买阿里云企业云服务器

iOS 逆向—-一键砸壳工具frida-ios-dump

首先给Mac安装frida,frida 依赖于 python,macOS 已经自带 python 所以不需要再去安装python。
frida的官网:https://www.frida.re/

在终端执行命令(建议所有的pip操作都走代理,不然速度慢不说,各种断开连接的问题也很让人头疼):

sudo pip install frida-tools
1
然后掏出你的越狱手机,启动 Cydia,添加软件源

软件源 Sources-> 编辑 Edit(右上角)-> 添加 Add(左上角)-> 输入 https://build.frida.re

通过刚才添加的软件源安装 frida 插件。根据手机进行安装:iPhone 5 及之前的机器为 32 位,5s 及之后的机器为 64 位。

然后通过USB链接手机,具体操作看这里:

https://blog.csdn.net/youshaoduo/article/details/81097802

两个端都安装完成之后可以用 USB 连接手机在 mac 终端中通过

frida-ps -U
1
命令测试,若输出手机上安装的 App 名称则说明安装成功:

YoussefdeMacBook-Pro:etc youssef$ frida-ps -U
PID Name
—- ———————————————
756 Mail
412 AppleIDAuthAgent
1806 AssetCacheLocatorService
432 BTServer
532 BlueTool
1304 CacheDeleteAppContainerCaches
1285 CacheDeleteDaily
1301 CacheDeleteITunesStore
626 CallHistorySyncHelper
601 CloudKeychainProxy
460 CommCenter
1283 ContactsCoreSpotlightExtension
668 DuetHeuristic-BM
1271 EscrowSecurityAlert
603 IDSKeychainSyncingProxy
122 IMDPersistenceAgent
1362 MTLCompilerService
548 MobileGestaltHelper
1159 MobileStorageMounter
1273 OTAPKIAssetTool
551 OTATaskingAgent
161 ReportCrash
782 ServerFileProvider
418 SpringBoard
442 UserEventAgent
1457 WeatherAppTodayWidget
520 WirelessRadioManagerd
…………..

然后就可以从github上下载frida-ios-dump了(此时不要断开电脑与手机的连接,下面要继续用),这里建议下载master分支上的,因为Mac自带的Python是2.7版本的,避免了一些不必要的麻烦。

进入下载好的frida-ios-dump目录,执行下面的命令,

sudo pip install -r requirements.txt –upgrade
1
等依赖库都装完之后,就可以直接使用命令(这里的app名称是指在手机桌面上显示的名称):

./dump.py app名称
1
进行砸壳了,砸壳完成后,会在frida-ios-dump目录里生成一个已砸壳的ipa文件。

iOS逆向工程一:砸壳

对一个iOS App进行逆向分析,首先需要砸壳,因为从AppStore中下载的App是加壳的,即加密过的,“砸壳”的过程就是解密的过程。对于公司内部的debug、release版本进行逆向时,不用砸壳处理,可以跳过此步骤。
砸壳工具有多种,常用的是dumpdecrypted 和 Clutch。下面以dumpdecryted为例。

dumpdecryted
从github上下载dumpdecryted源码后,make进行编译,得到dumpdecryted.dylib动态库,接下来利用dumpdecryted.dylib进行注入解密。

%title插图%num

砸壳工具安装完成之后,接下需要定位待解密的的可执行文件,先用ps定位目标应用,打开目标App,使用ps -e命令查看正在运行进程的可执行文件路径,在/var/mobile/Containers/Bundle/Application//TargetApp.app/TargetApp.
下一步就是获取TargetApp的Documents目录,因为需要把动态库复制到沙盒目录下,这里选择Documents目录。在info.plist文件中找到BundleID,后面com即为Bundle ID。然后使用cycript -p TargetApp命令注入进程,调用NSHomeDirectory()函数获取到Home目录,Home目录后加上/Documnets即可。
然后把dumpdecryted.dylib文件复制到Documents目录下。执行以下指令解密:
DYLD_INSERT_LIBRARIES=/usr/lib/dumpdecrypted.dylib /var/containers/Bundle/Application/59CEB222-4C4D-4A34-BC0F-8D38B9E3853D/MyApp.app/MyApp

解决iOS12版本的砸壳问题
然而如果iOS系统版本为12及以上,那么dumpdecryted和Clutch就无法正常使用了,需要使用CrackerXI+。
CrackerXI+的下载源地址为https://repo.netskao.cn/ ,下载后在设置里把CrackerXI Hook打开,在AppList中选择需要砸壳的应用就行了。

%title插图%num%title插图%num

解密后的应用存储在/var/mobile/Documents/CrackerXI,使用pp助手导出该ipa文件,完成砸壳。

%title插图%num

210. 课程表 II(JS实现)

210. 课程表 II(JS实现)
1 题目
现在你总共有 n 门课需要选,记为 0 到 n-1。
在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1]
给定课程总量以及它们的先决条件,返回你为了学完所有课程所安排的学习顺序。
可能会有多个正确的顺序,你只要返回一种就可以了。如果不可能完成所有课程,返回一个空数组。
示例 1:
输入: 2, [[1,0]]
输出: [0,1]
解释: 总共有 2 门课程。要学习课程 1,你需要先完成课程 0。因此,正确的课程顺序为 [0,1] 。
示例 2:
输入: 4, [[1,0],[2,0],[3,1],[3,2]]
输出: [0,1,2,3] or [0,2,1,3]
解释: 总共有 4 门课程。要学习课程 3,你应该先完成课程 1 和课程 2。并且课程 1 和课程 2 都应该排在课程 0 之后。
因此,一个正确的课程顺序是 [0,1,2,3] 。另一个正确的排序是 [0,2,1,3] 。
链接:https://leetcode-cn.com/problems/course-schedule-ii
2 思路
这道题还是考察图的拓扑排序,与之前课程表一的题相比,这道题多了输出序列的要求,不慌,在整个流程中添加几行保存序列的代码就可以了
3代码
/**
 * @param {number} numCourses
 * @param {number[][]} prerequisites
 * @return {number[]}
 */
var findOrder = function(numCourses, prerequisites) {
  const res = [];
  if (prerequisites.length === 0) {
    for (let i=0; i<numCourses; i++) {
        res.push(i);
    }
    return res;
  }
  const vexs = [];
  for (let arr of prerequisites) {
    if (!vexs[arr[0]]) {
      vexs[arr[0]] = new Node(arr[0]);
    }
    if (!vexs[arr[1]]) {
      vexs[arr[1]] = new Node(arr[1]);
    }
    let firstEdge = vexs[arr[1]].firstEdge;
    vexs[arr[1]].firstEdge = {vex: vexs[arr[0]], next: firstEdge};
    vexs[arr[0]].in++;
  }
  const stack = [];
  for (let i=0; i<numCourses; i++) {
    if (vexs[i]) {
      if (vexs[i].in === 0) stack.push(vexs[i]);
    } else {
      res.push(i);     // 保存没有任何边连接的节点
    }
  }
  while(stack.length > 0) {
    let currentVex = stack.pop();
    res.push(currentVex.val);    //保存节点
    let currentEdge = currentVex.firstEdge;
    while(currentEdge) {
      if (–currentEdge.vex.in === 0) {
        stack.push(currentEdge.vex);
      }
      currentEdge = currentEdge.next;
    }
  }
  return res.length < numCourses ? [] : res;
};
function Node(val) {
  this.val = val;
  this.firstEdge = null;
  this.in = 0;
}

211. 添加与搜索单词 – 数据结构设计(JS实现)

211. 添加与搜索单词 – 数据结构设计(JS实现)
1 题目
设计一个支持以下两种操作的数据结构:
void addWord(word)
bool search(word)
search(word) 可以搜索文字或正则表达式字符串,字符串只包含字母 . 或 a-z 。 . 可以表示任何一个字母。
示例:
addWord(“bad”)
addWord(“dad”)
addWord(“mad”)
search(“pad”) -> false
search(“bad”) -> true
search(“.ad”) -> true
search(“b…”) -> true
说明:
你可以假设所有单词都是由小写字母 a-z 组成的。
链接:https://leetcode-cn.com/problems/add-and-search-word-data-structure-design
2 思路
这道题还是用字典树的方法来存储单词,每个节点维护一个指针数组,搜索时若遇到小数点,则递归遍历当前数组所有指针进行下一步搜索
3代码
/**
 * Initialize your data structure here.
 */
var WordDictionary = function() {
    this.startIndex = ‘a’.charCodeAt();
    this.root = new Node();
};
/**
 * Adds a word into the data structure.
 * @param {string} word
 * @return {void}
 */
WordDictionary.prototype.addWord = function(word) {
    if (word.length === 0) return;
    let p = this.root;
    for (let letter of word) {
        let index = letter.charCodeAt() – this.startIndex;
        if (!p.list[index]) {
            p.list[index] = new Node();
        }
        p = p.list[index];
    }
    p.word = word;
};
/**
 * Returns if the word is in the data structure. A word could contain the dot character ‘.’ to represent any one letter.
 * @param {string} word
 * @return {boolean}
 */
WordDictionary.prototype.search = function(word) {
    if (word.length === 0) return false;
    return this.d(this.root, word);
};
WordDictionary.prototype.d = function(p, word) {
   if (!p) return false;
   if (word === ”) return !!p.word;
   let letter = word[0];
   if (letter === ‘.’) {
       for (let i=0; i<p.list.length; i++) {
           if (p.list[i] && this.d(p.list[i], word.slice(1))) {
               return true;
           }
       }
       return false;
   } else {
       let index = letter.charCodeAt() – this.startIndex;
       p = p.list[index];
       return this.d(p, word.slice(1));
   }
}
function Node() {
    this.list = [];
    this.word = null;
}
/**
 * Your WordDictionary object will be instantiated and called as such:
 * var obj = new WordDictionary()
 * obj.addWord(word)
 * var param_2 = obj.search(word)
 */