说实话,android source code从2.3到4.4变化是蛮多的,尤其是media部分,虽然总的框架是没有多大变化,但是找起代码来看还是挺麻烦的。在android里面最受伤的是使用了java,jni,jvm,Nativity c++等等,各种设计模式横行,当然在学习源码过程中也意识了编程语言基础,数据结构,设计模式的重要性。
android source code 经典的地方:
1. 大量使用了各种设计模式如单例模式,装饰模式,工程工厂模式,适配器模式等等。
2. 使用了binder驱动进行了IPC通信。
3. 重新设计了消息处理机制。
4. 加入了强弱指针管理。
5. 设计了activity安全的权限管理。
6. 对应用开发者可扩展,开发维护做出突出的贡献。
7. 使用了JNI技术。
8. 优化了电源管理服务。
。。。。。等等
当然,也有缺点地方。
1. android启动慢。
因为使用了jni,jvm原因需要加载很多类及类库,和各种服务的启动。为了用户体验,使用了sureface。
上述启动完后还要启动launcher,扫描各个应用信息等等。
2. android 是为嵌入式产品而开发的。实际上内存使用效果来看不是很理想,容易产生碎片,导致android使用越用越慢。
3. 主题定制少,缺乏大型游戏。
4. app常驻内存导致无法长时间待机。
好吧,不要抱怨那么多了,生活已经够无奈的了。开始分析下吧。
1. 在Android系统中,应用程序是由Activity组成的,因此,应用程序的启动过程实际上就是应用程序中的默认Activity的启动过程。即在桌面程序(launcher)启动时候,扫描各个app信息,在设备屏幕中点击应用程序图标的情景就会引发Android应用程序中的默认Activity的启动,从而把应用程序启动起来。这种启动方式的特点是会启动一个新的进程来加载相应的Activity。
2. 由上可知:默认启动activity是通过launcher(onClick方法)来启动的,其实就是解析AndroidManifest.xml中的activity标签及<intent-filter>标签。然后通过startActivitySafely方法启动activity。
1 Launcher.java (e:\baiduyundownload\intel_x86_sysimg_4.4_source_files_20131206\intel_x86_sysimg_4.4_source_files_20131206\packages\apps\launcher2\src\com\android\launcher2) 2 3 public void onClick(View v) { 4 // Make sure that rogue clicks don‘t get through while allapps is launching, or after the 5 // view has detached (it‘s possible for this to happen if the view is removed mid touch). 6 if (v.getWindowToken() == null) { 7 return; 8 } 9 10 if (!mWorkspace.isFinishedSwitchingState()) { 11 return; 12 } 13 14 Object tag = v.getTag(); 15 if (tag instanceof ShortcutInfo) { 16 // Open shortcut 17 final Intent intent = ((ShortcutInfo) tag).intent; 18 int[] pos = new int[2]; 19 v.getLocationOnScreen(pos); 20 intent.setSourceBounds(new Rect(pos[0], pos[1], 21 pos[0] + v.getWidth(), pos[1] + v.getHeight())); 22 23 boolean success = startActivitySafely(v, intent, tag); 24 25 if (success && v instanceof BubbleTextView) { 26 mWaitingForResume = (BubbleTextView) v; 27 mWaitingForResume.setStayPressed(true); 28 } 29 } else if (tag instanceof FolderInfo) { 30 if (v instanceof FolderIcon) { 31 FolderIcon fi = (FolderIcon) v; 32 handleFolderClick(fi); 33 } 34 } else if (v == mAllAppsButton) { 35 if (isAllAppsVisible()) { 36 showWorkspace(true); 37 } else { 38 onClickAllAppsButton(v); 39 } 40 } 41 }
boolean startActivitySafely(View v, Intent intent, Object tag) { boolean success = false; try { success = startActivity(v, intent, tag); } catch (ActivityNotFoundException e) { Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e); } return success; }
boolean startActivity(View v, Intent intent, Object tag) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { // Only launch using the new animation if the shortcut has not opted out (this is a // private contract between launcher and may be ignored in the future). boolean useLaunchAnimation = (v != null) && !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION); //useLaunchAnimation表示是否使用点击Launcher桌面上的图标,会先有图标放大的动画,然后才进入应用,2.3之前是没有这个选择的。 if (useLaunchAnimation) { ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getMeasuredWidth(), v.getMeasuredHeight()); startActivity(intent, opts.toBundle()); } else { startActivity(intent); } return true; } catch (SecurityException e) { Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); Log.e(TAG, "Launcher does not have the permission to launch " + intent + ". Make sure to create a MAIN intent-filter for the corresponding activity " + "or use the exported attribute for this activity. " + "tag="+ tag + " intent=" + intent, e); } return false; }
上面的
startActivity(intent, opts.toBundle());在launcher.java中没有找到定义,实际上是在launcher的基类中定义的,需要转到activity.java中查找定义。
Activity.java (base\core\java\android\app)
@Override public void startActivity(Intent intent, Bundle options) { if (options != null) { //第二个参数传入-1表示不需要这个Actvity结束后的返回结果。 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); } }
public void startActivityForResult(Intent intent, int requestCode, Bundle options) { if (mParent == null) { //这里的mParent肯定为null,因为是从launcher启动进来的,肯定没有父activity。 //这里的mInstrumentation是Activity类的成员变量,它的类型是Intrumentation,定义在frameworks/base/core/java/android/app/Instrumentation.java文件中,它用来监控应用程序和系统的交互。 //这里的mMainThread也是Activity类的成员变量,它的类型是ActivityThread,它代表的是应用程序的主线程,这里通过mMainThread.getApplicationThread获得它里面的ApplicationThread成员变量,它是一个Binder对象,后面我们会看到,ActivityManagerService会使用它来和ActivityThread来进行进程间通信。这里我们需注意的是,这里的mMainThread代表的是Launcher应用程序运行的进程。 //这里的mToken也是Activity类的成员变量,它是一个Binder对象的远程接口。 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()); } ....... }
Instrumentation.java (base\core\java\android\app) public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { IApplicationThread whoThread = (IApplicationThread) contextThread; if (mActivityMonitors != null) { synchronized (mSync) { final int N = mActivityMonitors.size(); for (int i=0; i<N; i++) { final ActivityMonitor am = mActivityMonitors.get(i); if (am.match(who, null, intent)) { am.mHits++; if (am.isBlocking()) { return requestCode >= 0 ? am.getResult() : null; } break; } } } } try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(); //这里的ActivityManagerNative.getDefault返回ActivityManagerService的远程接口,即ActivityManagerProxy接口,跟进去就知道了(IActivityManager)。 //intent.resolveTypeIfNeeded返回这个intent的MIME类型,一般没有AndroidManifest.xml设置MainActivity的MIME类型,因此,这里返回null。 int result = ActivityManagerNative.getDefault() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { } return null; }
ActivityManagerNative.java (base\core\java\android\app) public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, String profileFile, ParcelFileDescriptor profileFd, Bundle options) throws RemoteException {//这里已经非常接近核心了,1. 构造parcel data包和reply包,将相关要启动的intent数据打进去,然后通过远程对象mRemote的transact方法(binder IPC)投递到服务端( ActivityManagerService) 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); data.writeString(profileFile); if (profileFd != null) { data.writeInt(1); profileFd.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; }