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】利用自己定义View的重绘实现拖动移动,获取组件的尺寸

    以下利用一个app来说明怎样利用自己定义View的重绘实现拖动移动.获取组件的尺寸. 例如以下图,触摸拖动,或者轻轻点击屏幕都能移动图片.假设碰到文字,则会弹出提示. 这里是利用自己定义View的重绘 ...

  2. js -- fileData 实现文件断点续传

    前端实现文件的断点续传 一.一些知识准备 断点续传,既然有断,那就应该有文件分割的过程,一段一段的传. 以前文件无法分割,但随着HTML5新特性的引入,类似普通字符串.数组的分割,我们可以可以使用sl ...

  3. Spark Tachyon的命令行使用

    Tachyon命令行使用 Tachyon接口说明 接口操作示例 copyFromLocal copyToLocal ls和lsr count cat mkdir.rm.rmr和touch pin和un ...

  4. SuSe Linux Enterprise Server 10 With Sp2 安装过程图解

    SuSe Linux Enterprise Server 10 With Sp2 安装过程图解 650) this.width=650;" style="border-right- ...

  5. npm更新方法

    今天npm的版本更新发现小于3.0 尝试了npm install npm -g 安装么有成功换成了 cnpm install npm -g安装之后就可以

  6. Kinect 开发 —— 全息图

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

  7. wget 指令学习之递归抓取文档技巧

    在线上阅读文档的时候,有没有想将它抓取到本地,以备没有网的时候阅读只需? 先上指令: $ wget --user-agent="Mozilla/5.0 (X11; Linux x86_64) ...

  8. fsck---于检查并且试图修复文件系统中的错误

    fsck命令被用于检查并且试图修复文件系统中的错误.当文件系统发生错误四化,可用fsck指令尝试加以修复. -a:自动修复文件系统,不询问任何问题: -A:依照/etc/fstab配置文件的内容,检查 ...

  9. 【Uva 1289】Stacking Plates

    [Link]: [Description] 有n(1≤n≤50)堆盘子,第i堆盘子有hi个盘子(1≤hi≤50),从上到下直径不减.所有盘 子的直径均不超过10000.有如下两种操作. split:把 ...

  10. [TypeScript] Make Properties and Index Signatures Readonly in TypeScript

    TypeScript 2.0 introduced the readonly modifier which can be added to a property or index signature ...