ActivityManagerService(简称AMS)是Android系统的关键服务之中的一个。它的主要作用例如以下:

  • 管理系统中全部应用进程的整个生命周期
  • 管理应用进程中的Activity、Service、Broadcast和ContentProvider
  • 内存管理,低内存释放等

AMS是一个服务端,定义了IBinder接口。其它的进程能够通过Binder机制与AMS进行通信。

AMS由system_server进程启动的,并作为一个独立线程执行在system_server进程中。

以下就简略分析一下AMS的启动过程

system_server启动AMS

PATH:frameworks/base/services/java/com/android/server/SystemServer.java

启动过程大致例如以下:

SystemServer.main()–>SystemServer.run()。

private void run() {
......
startBootstrapServices();
startOtherServices();
......
} private void startBootstrapServices() {
......
// 启动AMS服务
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService(); // 初始化AMS的成员变量mSystemServiceManager
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
// 初始化AMS的成员变量mInstaller
mActivityManagerService.setInstaller(installer);
......
// 主要是创建system_server相应的ProcessRecord,并初始化
mActivityManagerService.setSystemProcess();
......
} private void startOtherServices() {
......
// 主要是创建并注冊SettingsProvider
mActivityManagerService.installSystemProviders();
......
// 系统启动前的准备工作,启动SystemUI和Home界面等
mActivityManagerService.systemReady(new Runnable() {...});
}

重点看一下mSystemServiceManager.startService():

public SystemService startService(String className) {
final Class<SystemService> serviceClass;
try {
serviceClass = (Class<SystemService>)Class.forName(className);
} catch (ClassNotFoundException ex) {
......
}
return startService(serviceClass);
} public <T extends SystemService> T startService(Class<T> serviceClass) {
final String name = serviceClass.getName();
Slog.i(TAG, "Starting " + name); // Create the service.
if (!SystemService.class.isAssignableFrom(serviceClass)) {
throw new RuntimeException("Failed to create " + name
+ ": service must extend " + SystemService.class.getName());
}
final T service;
try {
Constructor<T> constructor = serviceClass.getConstructor(Context.class);
//创建ActivityManagerService.Lifecycle对象
service = constructor.newInstance(mContext);
} catch (InstantiationException ex) {
......
} // 加入到成员变量mServices中
mServices.add(service); // Start it.
try {
// 执行ActivityManagerService.Lifecycle.onStart()
service.onStart();
} catch (RuntimeException ex) {
throw new RuntimeException("Failed to start service " + name
+ ": onStart threw an exception", ex);
}
return service;
}

ActivityManagerService.Lifecycle

PATH:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public static final class Lifecycle extends SystemService {
private final ActivityManagerService mService; public Lifecycle(Context context) {
super(context);
// 创建ActivityManagerServiceEx对象
mService = new ActivityManagerServiceEx(context);
} @Override
public void onStart() {
mService.start(); //执行ActivityManagerServiceEx.start()
} public ActivityManagerService getService() {
return mService;
}
}

当中,ActivityManagerServiceEx是ActivityManagerService的子类,定义例如以下:

public final class ActivityManagerServiceEx extends ActivityManagerService {
......
public ActivityManagerServiceEx(Context systemContext) {
super(systemContext);
mIsInHome = true;
}
......
}

这样,在new ActivityManagerServiceEx()时候。会调用到其父类ActivityManagerService的构造函数。

ActivityManagerService构造函数

PATH:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public ActivityManagerService(Context systemContext) {
mContext = systemContext;
mFactoryTest = FactoryTest.getMode();
mSystemThread = ActivityThread.currentActivityThread(); Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass()); //创建名称为“ActivityManager”的消息循环线程。
mHandlerThread = new ServiceThread(TAG,
android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
mHandlerThread.start(); //将该线程绑定到MainHandler,由MainHandler完毕消息的处理
mHandler = new MainHandler(mHandlerThread.getLooper()); //创建前台广播接收器,执行超时为10s
mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
"foreground", BROADCAST_FG_TIMEOUT, false);
//创建后台广播接收器。执行超时为60s
mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
"background", BROADCAST_BG_TIMEOUT, true);
mBroadcastQueues[0] = mFgBroadcastQueue;
mBroadcastQueues[1] = mBgBroadcastQueue; mServices = new ActiveServicesEx(this);
mProviderMap = new ProviderMap(this); //新建/data/system文件夹
File dataDir = Environment.getDataDirectory();
File systemDir = new File(dataDir, "system");
systemDir.mkdirs(); //创建BatteryStatsService服务
mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);
mBatteryStatsService.getActiveStatistics().readLocked();
mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
mOnBattery = DEBUG_POWER ? true
: mBatteryStatsService.getActiveStatistics().getIsOnBattery();
mBatteryStatsService.getActiveStatistics().setCallback(this); //创建ProcessStatsService服务
mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats")); //创建AppOpsService服务
mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler); //创建AtomicFile文件
mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml")); // User 0 is the first and only user that runs at boot.
mStartedUsers.put(0, new UserStartedState(new UserHandle(0), true));
mUserLru.add(Integer.valueOf(0));
updateStartedUserArrayLocked(); GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
ConfigurationInfo.GL_ES_VERSION_UNDEFINED); mTrackingAssociations = "1".equals(SystemProperties.get("debug.track-associations")); mConfiguration.setToDefaults();
mConfiguration.locale = Locale.getDefault(); mConfigurationSeq = mConfiguration.seq = 1;
mProcessCpuTracker.init(); mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
mStackSupervisor = new ActivityStackSupervisor(this);
mTaskPersister = new TaskPersister(systemDir, mStackSupervisor); mProcessCpuThread = new Thread("CpuTracker") {
@Override
public void run() {
while (true) {
try {
try {
synchronized(this) {
final long now = SystemClock.uptimeMillis();
long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
//Slog.i(TAG, "Cpu delay=" + nextCpuDelay
// + ", write delay=" + nextWriteDelay);
if (nextWriteDelay < nextCpuDelay) {
nextCpuDelay = nextWriteDelay;
}
if (nextCpuDelay > 0) {
mProcessCpuMutexFree.set(true);
this.wait(nextCpuDelay);
}
}
} catch (InterruptedException e) {
}
updateCpuStatsNow();
} catch (Exception e) {
Slog.e(TAG, "Unexpected exception collecting process stats", e);
}
}
}
}; Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
}

首先,创建了一个名为“ActivityManager”的消息循环线程,不断地接收其它进程发给AMS的消息;并把该消息循环线程与MainHandler绑定,这样,由MainHandler完毕消息的详细处理。

然后,创建了一些服务,并在/data/system文件夹下创建该服务须要的文件或文件夹,详细例如以下:

服务 服务说明 文件 文件说明
BatteryStatsService 电池状态管理 /data/system/batterystats.bin 记录包含电压在内的各种电池信息
ProcessStatsService 进程状态管理 /data/system/procstats 记录各个进程的状态信息
AppOpsService 应用操作权限管理 /data/system/appops.xml 存储各个app的权限设置和操作信息

另外,还创建了一个AtomicFile类型的文件mGrantFile ,文件路径为/data/system/urigrants.xml。

AtomicFile文件是通过创建一个备份文件来执行原子性操作的帮助类,保证文件读写的完整。

这样。system_server就完毕AMS的构造和启动。

回到system_server中,我们看到又调用了AMS的setSystemProcess方法。以下就分析一下该方法。

ActivityManagerService.setSystemProcess

public void setSystemProcess() {
try {
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
ServiceManager.addService("meminfo", new MemBinder(this));
ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
ServiceManager.addService("dbinfo", new DbBinder(this));
if (MONITOR_CPU_USAGE) {
ServiceManager.addService("cpuinfo", new CpuBinder(this));
}
ServiceManager.addService("permission", new PermissionController(this)); ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
"android", STOCK_PM_FLAGS);
mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader()); synchronized (this) {
ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
app.persistent = true;
app.pid = MY_PID;
app.maxAdj = ProcessList.SYSTEM_ADJ;
app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
mProcessNames.put(app.processName, app.uid, app);
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.put(app.pid, app);
}
updateLruProcessLocked(app, false, null);
updateOomAdjLocked();
}
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException(
"Unable to find android system package", e);
}
}

首先,向SystemServiceManager中加入了若干个服务:

服务 服务说明
activity AMS服务本身
procstats 进程状态管理
meminfo 获取内存信息
gfxinfo 监控分析GPU profiling信息
dbinfo 数据库相关服务
cpuinfo 获取cpu相关信息
permission 权限控制相关服务

然后。调用PMS的getApplicationInfo接口,获取名为”android”的应用程序信息。包名为”android”的apk即/system/framework/framework-res.apk。里面保存着系统GUI美化的相关文件,包含图标,弹出对话框的样式,动作特效,界面布局等。调用installSystemApplicationInfo载入framework-res.apk文件。

接着,调用newProcessRecordLocked新建一个ProcessRecord 对象app。ProcessRecord用来描写叙述一个进程的全部信息,包含该进程的全部activity和service等。在这里就是system_server(AMS就是在system_server进程中执行的)。

创建后,对app的一些成员变量进行初始化。包含设置为常驻内存执行;设置system_server的pid等。

最后。调用mProcessNames.put()将创建的ProcessRecord 对象app加入到ProcessMap< ProcessRecord >类型的成员变量mProcessNames中。

这里。app.processName=“system”。

这样,AMS就得到了system_server的ProcessRecord,以后AMS也能够管理system_server了。

继续回到system_server中。我们看到又调用了AMS的installSystemProviders方法,以下就分析一下该方法。

ActivityManagerService.installSystemProviders

public final void installSystemProviders() {
List<ProviderInfo> providers;
synchronized (this) {
ProcessRecord app = mProcessNames.get("system", Process.SYSTEM_UID);
providers = generateApplicationProvidersLocked(app);
if (providers != null) {
for (int i=providers.size()-1; i>=0; i--) {
ProviderInfo pi = (ProviderInfo)providers.get(i);
if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
Slog.w(TAG, "Not installing system proc provider " + pi.name
+ ": not system .apk");
providers.remove(i);
}
}
}
}
if (providers != null) {
mSystemThread.installSystemProviders(providers);
} mCoreSettingsObserver = new CoreSettingsObserver(this); //mUsageStatsService.monitorPackages();
}

首先,取出在setSystemProcess()中put到mProcessNames中的ProcessRecord对象app,即system_server的进程信息。

然后,调用generateApplicationProvidersLocked:

private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
List<ProviderInfo> providers = null;
try {
providers = AppGlobals.getPackageManager().
queryContentProviders(app.processName, app.uid,
STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
} catch (RemoteException ex) {
}
if (DEBUG_MU)
Slog.v(TAG_MU, "generateApplicationProvidersLocked, app.info.uid = " + app.uid);
int userId = app.userId;
if (providers != null) {
int N = providers.size();
app.pubProviders.ensureCapacity(N + app.pubProviders.size());
for (int i=0; i<N; i++) {
ProviderInfo cpi =
(ProviderInfo)providers.get(i);
boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo,
cpi.name, cpi.flags);
if (singleton && UserHandle.getUserId(app.uid) != 0) {
providers.remove(i);
N--;
i--;
continue;
} ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId);
if (cpr == null) {
cpr = new ContentProviderRecord(this, cpi, app.info, comp, singleton);
mProviderMap.putProviderByClass(comp, cpr);
}
if (DEBUG_MU)
Slog.v(TAG_MU, "generateApplicationProvidersLocked, cpi.uid = " + cpr.uid);
app.pubProviders.put(cpi.name, cpr);
if (!cpi.multiprocess || !"android".equals(cpi.packageName)) {
app.addPackage(cpi.applicationInfo.packageName, cpi.applicationInfo.versionCode,
mProcessStats);
}
ensurePackageDexOpt(cpi.applicationInfo.packageName);
}
}
return providers;
}

首先,调用PMS的queryContentProviders查找processName=“system”和uid=SYSTEM_UID的provider。即SettingsProvider。并获取其ProviderInfo 。

然后新建一个ContentProviderRecord(描写叙述一个ContentProvider,这里为SettingsProvider),并加入到AMS的成员变量mProviderMap和ProcessRecord对象的pubProviders中。

最后将SettingsProvider所在的package加入到ProcessRecord对象的pkglist中。

继续回到installSystemProviders()。调用installSystemProviders,先创建后注冊SettingsProvider。这样,其它进程就能够调用SettingsProvider。查询或改动一些系统设置了。

在installSystemProviders()的最后,注冊一个ContentObserver来监听SettingsProvider中的状态变化。

继续回到system_server中。我们看到又调用了AMS的systemReady方法。以下就分析一下该方法。

ActivityManagerService.systemReady

该函数主要完毕了以下几件事:

  • 在当前执行的进程中,查找在systemReady之前不同意启动的进程。然后调用removeProcessLocked()终止该进程并释放资源。推断条件例如以下:
boolean isAllowedWhileBooting(ApplicationInfo ai) {
return (ai.flags&ApplicationInfo.FLAG_PERSISTENT) != 0;
}
  • 载入若干配置信息和资源信息,代码例如以下:
retrieveSettings();
loadResourcesOnSystemReady(); private void retrieveSettings() {
final ContentResolver resolver = mContext.getContentResolver();
String debugApp = Settings.Global.getString(
resolver, Settings.Global.DEBUG_APP);
boolean waitForDebugger = Settings.Global.getInt(
resolver, Settings.Global.WAIT_FOR_DEBUGGER, 0) != 0;
boolean alwaysFinishActivities = Settings.Global.getInt(
resolver, Settings.Global.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
boolean forceRtl = Settings.Global.getInt(
resolver, Settings.Global.DEVELOPMENT_FORCE_RTL, 0) != 0;
......
} private void loadResourcesOnSystemReady() {
final Resources res = mContext.getResources();
mHasRecents = res.getBoolean(com.android.internal.R.bool.config_hasRecents);
mThumbnailWidth = res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
mThumbnailHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
}
  • 调用回调函数goingCallback.run()。主要完毕两件事:执行其它系统服务的systemready()或systemRunning();启动SystemUI。

    goingCallback.run()的实如今systemserver.java中:

mActivityManagerService.systemReady(new Runnable() {
@Override
public void run() {
Slog.i(TAG, "Making services ready");
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY); try {
mActivityManagerService.startObservingNativeCrashes();
} catch (Throwable e) {
reportWtf("observing native crashes", e);
} Slog.i(TAG, "WebViewFactory preparation");
WebViewFactory.prepareWebViewInSystemServer(); try {
startSystemUi(context); //启动SystemUI
} catch (Throwable e) {
reportWtf("starting System UI", e);
}
try {
if (mountServiceF != null) mountServiceF.systemReady();
} catch (Throwable e) {
reportWtf("making Mount Service ready", e);
}
try {
if (networkScoreF != null) networkScoreF.systemReady();
} catch (Throwable e) {
reportWtf("making Network Score Service ready", e);
}
try {
if (networkManagementF != null) networkManagementF.systemReady();
} catch (Throwable e) {
reportWtf("making Network Managment Service ready", e);
}
try {
if (networkStatsF != null) networkStatsF.systemReady();
} catch (Throwable e) {
reportWtf("making Network Stats Service ready", e);
}
try {
if (networkPolicyF != null) networkPolicyF.systemReady();
} catch (Throwable e) {
reportWtf("making Network Policy Service ready", e);
}
try {
if (connectivityF != null) connectivityF.systemReady();
} catch (Throwable e) {
reportWtf("making Connectivity Service ready", e);
}
try {
if (audioServiceF != null) audioServiceF.systemReady();
} catch (Throwable e) {
reportWtf("Notifying AudioService running", e);
}
Watchdog.getInstance().start(); // It is now okay to let the various system services start their
// third party code...
mSystemServiceManager.startBootPhase(
SystemService.PHASE_THIRD_PARTY_APPS_CAN_START); try {
if (wallpaperF != null) wallpaperF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying WallpaperService running", e);
}
try {
if (immF != null) immF.systemRunning(statusBarF);
} catch (Throwable e) {
reportWtf("Notifying InputMethodService running", e);
}
try {
if (locationF != null) locationF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying Location Service running", e);
}
try {
if (countryDetectorF != null) countryDetectorF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying CountryDetectorService running", e);
}
try {
if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying NetworkTimeService running", e);
}
try {
if (commonTimeMgmtServiceF != null) {
commonTimeMgmtServiceF.systemRunning();
}
} catch (Throwable e) {
reportWtf("Notifying CommonTimeManagementService running", e);
}
try {
if (textServiceManagerServiceF != null)
textServiceManagerServiceF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying TextServicesManagerService running", e);
}
try {
if (atlasF != null) atlasF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying AssetAtlasService running", e);
}
try {
// TODO(BT) Pass parameter to input manager
if (inputManagerF != null) inputManagerF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying InputManagerService running", e);
}
try {
if (telephonyRegistryF != null) telephonyRegistryF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying TelephonyRegistry running", e);
} try {
if (mediaRouterF != null) mediaRouterF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying MediaRouterService running", e);
} if (SystemProperties.get("persist.support.securetest").equals("1")) {
if (securityF != null) {
try {
securityF.systemReady(context);
} catch (Throwable e) {
reportWtf("Security Service ready", e);
}
}
}
}
});
  • 调用addAppLocked启动那些声明为“FLAG_SYSTEM|FLAG_PERSISTENT”的应用程序:
final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,
String abiOverride) {
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(info.processName, info.uid, true);
} else {
......
}
......
// This package really, really can not be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
info.packageName, false, UserHandle.getUserId(app.uid));
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ info.packageName + ": " + e);
}
//推断条件
if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
== (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
app.persistent = true;
app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
}
//假设该app的IApplicationThread等于null,而且没有在ArrayList<ProcessRecord>类型
//的成员变量mPersistentStartingProcesses中,
//启动该app,并把它加入到mPersistentStartingProcesses中。
if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
startProcessLocked(app, "added application", app.processName, abiOverride,
null /* entryPoint */, null /* entryPointArgs */);
} return app;
}
  • 广播两个消息:ACTION_USER_STARTED和ACTION_USER_STARTING。标识用户已经started
Intent intent = new Intent(Intent.ACTION_USER_STARTED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
false, false, MY_PID, Process.SYSTEM_UID, mCurrentUserId);
intent = new Intent(Intent.ACTION_USER_STARTING);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
broadcastIntentLocked(null, null, intent,
null, new IIntentReceiver.Stub() {
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser)
throws RemoteException {
}
}, 0, null, null,
INTERACT_ACROSS_USERS, AppOpsManager.OP_NONE,
true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
} catch (Throwable t) {
......
  • 调用startHomeActivityLocked()启动HOME界面。

这样,ActivityManagerService的启动和初始化就完毕了。

[Android5.1]ActivityManagerService启动过程分析的更多相关文章

  1. 开机SystemServer到ActivityManagerService启动过程分析

    开机SystemServer到ActivityManagerService启动过程 一 从Systemserver到AMS zygote-> systemserver:java入层口: /** ...

  2. ActivityManagerService启动过程分析

    之前讲Android的View的绘制原理和流程的时候,讲到过在Android调用setContentView之后,Android调用了一个prepreTravle的方法,这里面就提到了Activity ...

  3. Activity启动过程分析

    Android的四大组件中除了BroadCastReceiver以外,其他三种组件都必须在AndroidManifest中注册,对于BroadCastReceiver来说,它既可以在AndroidMa ...

  4. startActivity启动过程分析(转)

    基于Android 6.0的源码剖析, 分析android Activity启动流程,相关源码: frameworks/base/services/core/java/com/android/serv ...

  5. ASP.Net Core MVC6 RC2 启动过程分析[偏源码分析]

    入口程序 如果做过Web之外开发的人,应该记得这个是标准的Console或者Winform的入口.为什么会这样呢? .NET Web Development and Tools Blog ASP.NE ...

  6. 【Android】应用程序Activity启动过程分析

    在Android系统中,有两种操作会引发Activity的启动,一种用户点击应用程序图标时,Launcher会为我们启动应用程序的主Activity:应用程序的默认Activity启动起来后,它又可以 ...

  7. Neutron分析(2)——neutron-server启动过程分析

    neutron-server启动过程分析 1. /etc/init.d/neutron-server DAEMON=/usr/bin/neutron-server DAEMON_ARGS=" ...

  8. linux视频学习7(ssh, linux启动过程分析,加解压缩,java网络编程)

    回顾数据库mysql的备份和恢复: show databases; user spdb1; show tables; 在mysql/bin目录下 执行备份: ./mysqldump -u root - ...

  9. Spark Streaming应用启动过程分析

    本文为SparkStreaming源码剖析的第三篇,主要分析SparkStreaming启动过程. 在调用StreamingContext.start方法后,进入JobScheduler.start方 ...

随机推荐

  1. android Manifest.xml选项

    结构 继承关系 public final class Manifest extends Object java.lang.Object android.Manifest 内部类 class  Mani ...

  2. 负载均衡(LB)具体解释

    二.LB LoadBalance就是把负载均衡分配到集群的各个节点,从而提高总体的吞吐能力.Oracle 10g RAC提供了两种手段来实现负载,其一是通过Connection Balancing.依 ...

  3. 关于集合类set

    list中允许有重复的元素,而set中不允许有重复的元素. package cn.hncu.Test; import java.util.HashMap; import java.util.Map; ...

  4. php 内置的 html 格式化/美化tidy函数 -- 让你的HTML更美观

    php 内置的 html 格式化/美化tidy函数 https://github.com/htacg/tidy-html5 # HTML 格式化 function beautify_html($htm ...

  5. Kinect 开发 —— 全息图

    Kinect的另一个有趣的应用是伪全息图(pseudo-hologram).3D图像可以根据人物在Kinect前面的各种位置进行倾斜和移动.如果方法够好,可以营造出3D控件中3D图像的效果,这样可以用 ...

  6. POj 2159 Dividing

    Dividing Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 71453   Accepted: 18631 Descri ...

  7. 小程序中关于获取app实例与当前组件

    1.getApp()来获取 App 实例 2.getCurrentPages()获取前页面栈

  8. Web开发中,使用表格来展示每个角色对应的权限

    通过表格这种方式,来展示角色和权限之间的关系,挺好的.还有很多场景,都可以用这种方式. 角色权限表 权限 系统管理员 文章管理员 相册管理员 留言管理员 个人信息管理 查看个人信息 √ √ √ √ 编 ...

  9. 洛谷 P2372 yyy2015c01挑战算周长

    P2372 yyy2015c01挑战算周长 题目背景 yyy2015c01快速的解决了问题,受到邻居们的赞许,高兴的回到家,把糖给了妈妈,吃了香喷喷的午饭,又睡了一个甜甜的午觉,感觉人生真美好.下午爸 ...

  10. 项目EasyUi和JS中遇到的问题总汇

    近期因为项目用到EasyUi,曾经仅仅是听过,可是没有详细用过.仅仅能一边学一边做.如今将做的过程中遇到的一些难点总结例如以下,以备后用: EsayUi使用: Json格式:key:value,key ...