QSTitle创建流程
来源:互联网 发布:不需要网络的游戏大全 编辑:程序博客网 时间:2024/05/12 14:45
本文将分析Android6.0中下拉状态栏快捷开关QSTitle组件的创建流程,从开机init过程开始至具体的每个QSTitle对象具体的创建,如何添加入下拉状态栏,对QSTitle的相关整体流程进行梳理。
android设备上电,引导程序引导进入boot(通常是uboot),加载initramfs、kernel镜像,启动kernel后,进入用户态程序。第一个用户空间程序是init, PID固定是1.
在android系统上,init.cpp的代码位于/system/core/init下,基本功能有:
- 管理设备
- 解析并处理Android启动脚本init.rc
- 实时维护这个init.rc中的服务,包括加载 Zygote
这里不过过多分析init.cpp部分,重点关注Zygote的启动流程。init,cpp部分推荐相关文档http://my.oschina.net/youranhongcha/blog/469028
init.rc配置文件在 Android 6.0 代码中位于 system/core/rootdir
/init.zygote32.rc,具体内容为:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class main socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart media onrestart restart netd writepid /dev/cpuset/foreground/tasks
其中:
- 关键字 service 表示告诉 init 进程创建名为 zygote 的进程,所要执行的程序是 /system/bin/app_process,后面的都是传递的参数。
- 注意参数 --start-system-server,说明要启动 SystemServer
- socket zygote stream 660 root system 表示创建名为 zygote 的 socket。
- 后面的 onrestart 关键字表示 zygote 进程重启时所需执行的命令。
Zygote 的启动
从中我们可以得出结论: zygote 只是服务的名称,与此服务对应的程序是 app_process 程序,我们研究 zygote 的实现,就是要研究 app_process 程序。
app_process 代码位于 frameworks/base/cmds/app_process
/app_main.cpp,入口函数为 main。
main 的大体流程为:
- 创建一个 AppRuntime 实例 runtime
- 解析传入的命令行参数
- 判断调用哪一个 runtime.start,传入对应的参数
- 由于 init.zygote32.rc 中传入参数 -Xzygote /system/bin --zygote --start-system-server,因此将执行:
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
由此可知,app_process 没干什么主要的事情,只是跳转到 Java 类 com.android.internal.os.ZygoteInit,看来工作都在 ZygoteInit 中完成。但ZygoteInit如何启动呢?
我们来看看AppRuntime 。
AndroidRuntime
runtime.start方法来自于 AppRuntime 的父类 AndroidRuntime,代码位于 frameworks/base/core/jni/AndroidRuntime.cpp。重点看看 AndroidRuntime start 方法,它主要做了三件事:
首先是创建虚拟机:
/* start the virtual machine */ JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; if (startVm(&mJavaVM, &env, zygote) != 0) { return; } onVmCreated(env);
之后是调用 startReg 函数注册 JNI 方法:
/* * Register android functions. */ if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; }
最后构建参数、创建 JNI 类对象,获取 main 方法,并最终执行下面一行执行 main 入口:
env->CallStaticVoidMethod(startClass, startMeth, strArray);
这样我们就成功从 AndroidRuntime.cpp中启动了一个虚拟机,并加载了 Java 类 ZygoteInit,并进入到它的 main 方法中执行。
ZygoteInit
之后就来到了 ZygoteInit.java 的 main 方法,代码位frameworks/
base/core/java/com/android/internal/os/ZygoteInit.java。来看其 main 方法:
public static void main(String argv[]) { try { ... registerZygoteSocket(socketName); ... if (startSystemServer) { startSystemServer(abiList, socketName); } ... runSelectLoop(abiList); ... } catch (...) { ... }}
首先,调用 registerZygoteSocket 创建了一个名为 zygote 的 socket:
registerZygoteSocket(socketName);
之后启动 SystemServer 组件:
if (startSystemServer) {startSystemServer(abiList, socketName);}
最后调用 runSelectLoopMode 进入一个死循环,等待接受 socket 上由 ActivityManagerService 发来的请求创建应用程序的请求:
runSelectLoop(abiList);
对后startSystemServer(abiList, socketName);进行分析:
启动 SystemServer 组件
SystemServer 名为系统服务进程,负责启动 Android 系统的关键服务。来看看函数的主要实现:
private static boolean startSystemServer(String abiList, String socketName) throws MethodAndArgsCaller, RuntimeException { ... /* Request to fork the system server process */ pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); ... /* For child process */ if (pid == 0) { ... handleSystemServerProcess(parsedArgs); } return true;}
这里调用了 Zygote 的静态方法 forkSystemServer 来创建 SystemServer 进程。
在forkSystemServer 中进行JNI调用forkSystemServer - com_android_internal_os_Zygote_nativeForkSystemServer - ForkAndSpecializeCommon来成功fork一个新进程。
子进程创建好之后,有一句
handleSystemServerProcess(parsedArgs);
进入handleSystemServerProcess:
/** * Finish remaining work for the newly forked system server process. */ private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller { ... final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH"); ... if (...) { ... } else { ClassLoader cl = null; if (systemServerClasspath != null) { cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader()); Thread.currentThread().setContextClassLoader(cl); } /* * Pass the remaining arguments to SystemServer. */ RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl); }
从中可以看出,我们从环境变量 SYSTEMSERVERCLASSPATH 拿到 SystemServer 的类名,之后载入进来,最后使用 RuntimeInit.zygoteInit 来运行,它来执行 SystemServer 的 main 方法。
看一下RuntimeInit.zygoteInit():
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { ... commonInit(); // 基本设置(异常捕获、时区、HTTP User-Agent 等) nativeZygoteInit(); applicationInit(targetSdkVersion, argv, classLoader); // 调用 Main 方法}
其中 nativeZygoteInit() 是一个 jni 调用,位于 AndroidRuntime.cpp:
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz){ gCurRuntime->onZygoteInit();}
onZygoteInit() 是 AppRuntime 中的方法,具体为:
virtual void onZygoteInit(){ sp<ProcessState> proc = ProcessState::self(); ALOGV("App process: starting thread pool.\n"); proc->startThreadPool();}
启动了一个线程池。nativeZygoteInit() 就分析到这里,由此可见,Zygote 启动 SystemServer 的过程就算完了,之后的,都是 SystemServer 内部的事情了。
SystemServer.main()
上面说到RuntimeInit.zygoteInit 来执行 SystemServer.main方法。我们来看SystemServer.main():
/** * The main entry point from zygote. */ public static void main(String[] args) { new SystemServer().run(); }
生成SystemServer对象并跳转到了run();
去run()看看:
private void run() { ...... // Start services. try { startBootstrapServices(); startCoreServices(); startOtherServices(); ...... } catch (Throwable ex) { ... throw ex; } ... // Loop forever. Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited");}
在这里启动了一些服务,我们重点去看startBootstrapServices();
private void startBootstrapServices() { ...... Installer installer = mSystemServiceManager.startService(Installer.class); // Activity manager runs the show. mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService(); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); ...... }
Activity manager运行
再回到SystemServer,run()有这么一句:
startOtherServices();
startOtherServices()代码:
private void startOtherServices() { final Context context = mSystemContext; AccountManagerService accountManager = null; ContentService contentService = null; ....... mActivityManagerService.systemReady(new Runnable() { @Override public void run() { ...... try { startSystemUi(context); } catch (Throwable e) { reportWtf("starting System UI", e); } .......
在这里mActivityManagerService.systemReady创建线程去调用startSystemUi(context);
static final void startSystemUi(Context context) { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.android.systemui", "com.android.systemui.SystemUIService")); //Slog.d(TAG, "Starting service: " + intent); context.startServiceAsUser(intent, UserHandle.OWNER); }
通过intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
设置启动systemui程序的SystemUIService
进入SystemUIService:
public class SystemUIService extends Service { @Override public void onCreate() { super.onCreate(); ((SystemUIApplication) getApplication()).startServicesIfNeeded(); }......
onCreate方法中获得SystemUIApplication对象并调用其startServicesIfNeeded方法:
public void startServicesIfNeeded() { final int N = SERVICES.length; for (int i=0; i<N; i++) { Class<?> cl = SERVICES[i]; try { mServices[i] = (SystemUI)cl.newInstance();//加载实例 } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InstantiationException ex) { throw new RuntimeException(ex); } mServices[i].mContext = this; mServices[i].mComponents = mComponents; mServices[i].start();//start服务 if (mBootCompleted) { mServices[i].onBootCompleted(); } } mServicesStarted = true; }
这个方法中,首先判断mServicesStarted标志为来判断SystemUI相关的服务是否启动,
同时根据系统配置文件来检查ActivityManagerService是否finishBooting。
可以看到这里有个mServices数组,并通过for循环加载它们的实例并调用它们的start();
但是mServices数组具体开启了哪些服务呢?
来看看SystemUIApplication类中的变量:
private final Class<?>[] SERVICES = new Class[] { com.android.systemui.tuner.TunerService.class, com.android.systemui.keyguard.KeyguardViewMediator.class, com.android.systemui.recents.Recents.class, com.android.systemui.volume.VolumeUI.class, com.android.systemui.statusbar.SystemBars.class, com.android.systemui.usb.StorageNotification.class, com.android.systemui.power.PowerUI.class, com.android.systemui.media.RingtonePlayer.class, com.android.systemui.keyboard.KeyboardUI.class, };
可以看到这里有很多sysytemui中常用的服务,后面将重点分析SystemBars及TunerService。
直接进入SystemBars.start():
public void start() { mServiceMonitor = new ServiceMonitor(TAG, DEBUG, mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this); mServiceMonitor.start(); // will call onNoService if no remote service is found }
start中创建ServiceMonitor实例并start();
注释中说明,/服务没启动时,ServiceMonitor会回调SystemBars的onNoService/
所以去看SystemBars的onNoService:
public void onNoService() { createStatusBarFromConfig(); // fallback to using an in-process implementation }
直接去看createStatusBarFromConfig():
private void createStatusBarFromConfig() { final String clsName = mContext.getString(R.string.config_statusBarComponent); if (clsName == null || clsName.length() == 0) { throw andLog("No status bar component configured", null); } Class<?> cls = null; try { cls = mContext.getClassLoader().loadClass(clsName); } catch (Throwable t) { throw andLog("Error loading status bar component: " + clsName, t); } try { mStatusBar = (BaseStatusBar) cls.newInstance(); } catch (Throwable t) { throw andLog("Error creating status bar component: " + clsName, t); } mStatusBar.mContext = mContext; mStatusBar.mComponents = mComponents; mStatusBar.start(); }
clsName得到的string为com.android.systemui.statusbar.phone.PhoneStatusBar
通过反射机制得到PhoneStatusBar实例:
cls = mContext.getClassLoader().loadClass(clsName);...mStatusBar = (BaseStatusBar) cls.newInstance();
并调用start方法:
PhoneStatusBar继承自BaseStatusBar;
PhoneStatusBar中调用了BaseStatusBar的start()
BaseStatusBar.start():
public void start() { mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); mWindowManagerService = WindowManagerGlobal.getWindowManagerService(); mDisplay = mWindowManager.getDefaultDisplay(); mDevicePolicyManager = (DevicePolicyManager)mContext.getSystemService( Context.DEVICE_POLICY_SERVICE); mNotificationColorUtil = NotificationColorUtil.getInstance(mContext); mNotificationData = new NotificationData(this); mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); mDreamManager = IDreamManager.Stub.asInterface( ServiceManager.checkService(DreamService.DREAM_SERVICE)); mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); ....... //在这里实例化了许多systemui常用的对象,服务,Manager,Observer等等 ....... createAndAddWindows(); //本本文而言一个非常重要的方法
查看createAndAddWindows():
protected abstract void createAndAddWindows();
是个抽象方法,很显然调用去了BaseStatusBar的子类中,即PhoneStatusBar中
PhoneStatusBar的createAndAddWindows():
@Override public void createAndAddWindows() { addStatusBarWindow(); } private void addStatusBarWindow() { makeStatusBarView();//关键方法,创建StatusBarView mStatusBarWindowManager = new StatusBarWindowManager(mContext); mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight()); }
可以看到这里最终调用了makeStatusBarView方法:
protected PhoneStatusBarView makeStatusBarView() { final Context context = mContext; Resources res = context.getResources(); updateDisplaySize(); // populates mDisplayMetrics updateResources(); mStatusBarWindow = (StatusBarWindowView) View.inflate(context, R.layout.super_status_bar, null); ........ mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar); mStatusBarView.setBar(this); PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder); mStatusBarView.setPanelHolder(holder); mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById( R.id.notification_panel); mNotificationPanel.setStatusBar(this); if (!ActivityManager.isHighEndGfx()) { mStatusBarWindow.setBackground(null); mNotificationPanel.setBackground(new FastColorDrawable(context.getColor( R.color.notification_panel_solid_background))); } ........ mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header); mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view); mKeyguardBottomArea = (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area); ........ //可以看到这里完成了许多systemui关键组件的view创建。这个方法很重要。 ........ // Set up the quick settings tile panel mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel); if (mQSPanel != null) { final QSTileHost qsh = new QSTileHost(mContext, this, mBluetoothController, mLocationController, mRotationLockController, mNetworkController, mZenModeController, mHotspotController, mCastController, mFlashlightController, mUserSwitcherController, mKeyguardMonitor, mSecurityController, mAudioProfileController ); mQSPanel.setHost(qsh); mQSPanel.setTiles(qsh.getTiles()); mHeader.setQSPanel(mQSPanel); qsh.setCallback(new QSTileHost.Callback() { @Override public void onTilesChanged() { mQSPanel.setTiles(qsh.getTiles()); } }); } .........
看到QSPanel,发现了我们的目标,它是下拉状态栏的一个关键类。
在mQSPanel加载xml布局之后,创建QSTileHost对象。
直接去看QSTileHost的继承关系及构造方法:
public class QSTileHost implements QSTile.Host, Tunable { ....... //这里QSTileHost继承了Tunable接口,下文将有一个非常经典的java回调实现public QSTileHost(Context context, PhoneStatusBar statusBar, ........ TunerService.get(mContext).addTunable(this, TILES_SETTING); //回调实现的第一步 //这里传了this。 //将继承了Tunable接口的QSTileHost传递给TunerService的addTunable(); }
重点即为TunerService的addTunable。TunerService看起来有点眼熟,向上查看文章,它和systembars一起
在SystemUIApplication中被实例化并开启
来看TunerService的addTunable:
public void addTunable(Tunable tunable, String... keys) { for (String key : keys) { addTunable(tunable, key); } } private void addTunable(Tunable tunable, String key) { if (!mTunableLookup.containsKey(key)) { mTunableLookup.put(key, new ArrayList<Tunable>()); } mTunableLookup.get(key).add(tunable); Uri uri = Settings.Secure.getUriFor(key); if (!mListeningUris.containsKey(uri)) { mListeningUris.put(uri, key); mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser); } // Send the first state. String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser); //这里的value将获得一个长字符,包含了所有系统QSTitle组件名,在后面进行分割,生成具体的QSTitle对象 //例子: wifi,location,dataconnection,hotspot,audioprofile,bt,rotation,airplane,screenshot tunable.onTuningChanged(key, value);//回调第二步,addTunable传递来的QSTileHost对象调用自己的onTuningChanged方法 }
来看QSTileHost的onTuningChanged()
@Override public void onTuningChanged(String key, String newValue) { if (!TILES_SETTING.equals(key)) { return; } final List<String> tileSpecs = loadTileSpecs(newValue);//切割传递来的newValue为List if (tileSpecs.equals(mTileSpecs)) return; for (Map.Entry<String, QSTile<?>> tile : mTiles.entrySet()) { if (!tileSpecs.contains(tile.getKey())) { tile.getValue().destroy(); } } final LinkedHashMap<String, QSTile<?>> newTiles = new LinkedHashMap<>(); for (String tileSpec : tileSpecs) { if (mTiles.containsKey(tileSpec)) { newTiles.put(tileSpec, mTiles.get(tileSpec)); } else { if (DEBUG) Log.d(TAG, "Creating tile: " + tileSpec); try { newTiles.put(tileSpec, createTile(tileSpec)); //createTile()中根据上文切割出的QSTitle名创建相应的对象 } catch (Throwable t) { } } } mTileSpecs.clear(); mTileSpecs.addAll(tileSpecs); mTiles.clear(); mTiles.putAll(newTiles); if (mCallback != null) { mCallback.onTilesChanged(); } }
看看createTile(tileSpec)
protected QSTile<?> createTile(String tileSpec) { if (tileSpec.equals("wifi")) return new WifiTile(this); else if (tileSpec.equals("bt")) return new BluetoothTile(this); else if (tileSpec.equals("inversion")) return new ColorInversionTile(this); else if (tileSpec.equals("cell")) return new CellularTile(this); else if (tileSpec.equals("airplane")) return new AirplaneModeTile(this); else if (tileSpec.equals("dnd")) return new DndTile(this); else if (tileSpec.equals("rotation")) return new RotationLockTile(this); else if (tileSpec.equals("flashlight")) return new FlashlightTile(this); else if (tileSpec.equals("location")) return new LocationTile(this); else if (tileSpec.equals("cast")) return new CastTile(this); else if (tileSpec.equals("hotspot")) return new HotspotTile(this); else throw new IllegalArgumentException("Bad tile spec: " + tileSpec); }
可以看到这里具体创建了QSTitle的各个对象。
那么这些QSTitle对象又是如何加载到QSPanel的View中呢?
而QSPanel在哪加入到了StatusBarHeaderView中。
回头在看看PhoneStatusBar的makeStatusBarView方法:
// Set up the quick settings tile panel mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel); if (mQSPanel != null) { final QSTileHost qsh = new QSTileHost(mContext, this, mBluetoothController, mLocationController, mRotationLockController, mNetworkController, mZenModeController, mHotspotController, mCastController, mFlashlightController, mUserSwitcherController, mKeyguardMonitor, mSecurityController, mAudioProfileController ); mQSPanel.setHost(qsh); mQSPanel.setTiles(qsh.getTiles()); mHeader.setQSPanel(mQSPanel);//mHeader->StatusBarHeaderView QSPanel加入到了StatusBarHeaderView中。 qsh.setCallback(new QSTileHost.Callback() { @Override public void onTilesChanged() { mQSPanel.setTiles(qsh.getTiles()); } }); }
刚才我们从QSTileHost的构造函数开始,分析了具体每个QSTitle的实例化。我们现在创建QSTileHost之后,又发生了什么。
mQSPanel.setHost(qsh);//将QSTileHost对象放入QSPanelmQSPanel.setTiles(qsh.getTiles());/*QSTileHost获得title用来设置QSPanel的title,从函数名来看,很像是我们上面问题的答案*/
看看qsh.getTiles()及mQSPanel.setTiles()
@Override public Collection<QSTile<?>> getTiles() { return mTiles.values();//获得title值 } public void setTiles(Collection<QSTile<?>> tiles) { for (TileRecord record : mRecords) { removeView(record.tileView); } mRecords.clear(); for (QSTile<?> tile : tiles) { addTile(tile);//在这里,具体的每个QStitle在这里被addTile进了QSPanel } if (isShowingDetail()) { mDetail.bringToFront(); } }
看看addTile():
private void addTile(final QSTile<?> tile) { final TileRecord r = new TileRecord(); r.tile = tile; r.tileView = tile.createTileView(mContext); r.tileView.setVisibility(View.GONE); final QSTile.Callback callback = new QSTile.Callback() { @Override public void onStateChanged(QSTile.State state) { if (!r.openingDetail) { drawTile(r, state); } } @Override public void onShowDetail(boolean show) { QSPanel.this.showDetail(show, r); } @Override public void onToggleStateChanged(boolean state) { if (mDetailRecord == r) { fireToggleStateChanged(state); } } @Override public void onScanStateChanged(boolean state) { r.scanState = state; if (mDetailRecord == r) { fireScanStateChanged(r.scanState); } } @Override public void onAnnouncementRequested(CharSequence announcement) { announceForAccessibility(announcement); } }; r.tile.setCallback(callback); final View.OnClickListener click = new View.OnClickListener() { @Override public void onClick(View v) { r.tile.click(); } }; final View.OnClickListener clickSecondary = new View.OnClickListener() { @Override public void onClick(View v) { r.tile.secondaryClick(); } }; final View.OnLongClickListener longClick = new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { r.tile.longClick(); return true; } }; r.tileView.init(click, clickSecondary, longClick); r.tile.setListening(mListening); callback.onStateChanged(r.tile.getState()); r.tile.refreshState(); mRecords.add(r); addView(r.tileView);//加载进QSPanel }
addTile()中创建了一个callback,实际运行中Title刷新,点击事件等许多操作都将与这个callback挂钩
同时,最后addView函数也将这个QSTitle加载进了QSPanel中。
- QSTitle创建流程
- live555 创建基本创建流程
- JBPM创建子流程
- 进程创建流程
- 线程创建流程
- GEF创建流程
- HDFS文件创建流程
- 创建网页流程
- Opengl ES创建流程
- 浅析adb创建流程
- 浅析adb创建流程
- Win32窗口创建流程--
- OOBE创建流程
- 浅析adb创建流程
- 浅析adb创建流程
- 创建一个app流程
- ADF 项目创建流程
- ActiveX控件创建流程
- 文章标题
- java集合类简要汇总
- 数据库知识复习--三大范式
- Hive的常用语法(Hive QL)
- java将List中的数据导入到excel表中
- QSTitle创建流程
- 什么样的产品可以成功?
- Detect Capital
- python 调用 shell python shell 间变量传递
- error adding symbols: DSO missing from command line
- RecyclerView3-面向接口优雅地实现多类型列表
- 运维笔记30 (lvs负载均衡的(nat,tun,dr三种模式,ldirectord健康检测,ldirectord结合heartbeat)keepalived+lvs介绍)
- 求素数,判断素数,筛法
- Java中static静态变量的初始化解析