am 88e62579: Merge change 24060 into eclair

Merge commit '88e625795943dea84b2e7c32f37e71303143b728' into eclair-plus-aosp

* commit '88e625795943dea84b2e7c32f37e71303143b728':
  Integrated the profiler into the framework. We run it all the time if the persist.sampling_profiler
This commit is contained in:
Bob Lee
2009-09-08 13:40:51 -07:00
committed by Android Git Automerger
5 changed files with 315 additions and 121 deletions

View File

@@ -68,6 +68,7 @@ import android.view.WindowManagerImpl;
import com.android.internal.os.BinderInternal; import com.android.internal.os.BinderInternal;
import com.android.internal.os.RuntimeInit; import com.android.internal.os.RuntimeInit;
import com.android.internal.os.SamplingProfilerIntegration;
import com.android.internal.util.ArrayUtils; import com.android.internal.util.ArrayUtils;
import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl; import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
@@ -87,6 +88,8 @@ import java.util.Map;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import dalvik.system.SamplingProfiler;
final class IntentReceiverLeaked extends AndroidRuntimeException { final class IntentReceiverLeaked extends AndroidRuntimeException {
public IntentReceiverLeaked(String msg) { public IntentReceiverLeaked(String msg) {
super(msg); super(msg);
@@ -126,7 +129,7 @@ public final class ActivityThread {
private static final int LOG_ON_PAUSE_CALLED = 30021; private static final int LOG_ON_PAUSE_CALLED = 30021;
private static final int LOG_ON_RESUME_CALLED = 30022; private static final int LOG_ON_RESUME_CALLED = 30022;
public static final ActivityThread currentActivityThread() { public static final ActivityThread currentActivityThread() {
return (ActivityThread)sThreadLocal.get(); return (ActivityThread)sThreadLocal.get();
} }
@@ -314,7 +317,7 @@ public final class ActivityThread {
public ApplicationInfo getApplicationInfo() { public ApplicationInfo getApplicationInfo() {
return mApplicationInfo; return mApplicationInfo;
} }
public boolean isSecurityViolation() { public boolean isSecurityViolation() {
return mSecurityViolation; return mSecurityViolation;
} }
@@ -322,7 +325,7 @@ public final class ActivityThread {
/** /**
* Gets the array of shared libraries that are listed as * Gets the array of shared libraries that are listed as
* used by the given package. * used by the given package.
* *
* @param packageName the name of the package (note: not its * @param packageName the name of the package (note: not its
* file name) * file name)
* @return null-ok; the array of shared libraries, each one * @return null-ok; the array of shared libraries, each one
@@ -350,7 +353,7 @@ public final class ActivityThread {
* result is a single string with the names of the libraries * result is a single string with the names of the libraries
* separated by colons, or <code>null</code> if both lists * separated by colons, or <code>null</code> if both lists
* were <code>null</code> or empty. * were <code>null</code> or empty.
* *
* @param list1 null-ok; the first list * @param list1 null-ok; the first list
* @param list2 null-ok; the second list * @param list2 null-ok; the second list
* @return null-ok; the combination * @return null-ok; the combination
@@ -378,7 +381,7 @@ public final class ActivityThread {
if (dupCheck && ArrayUtils.contains(list1, s)) { if (dupCheck && ArrayUtils.contains(list1, s)) {
continue; continue;
} }
if (first) { if (first) {
first = false; first = false;
} else { } else {
@@ -390,7 +393,7 @@ public final class ActivityThread {
return result.toString(); return result.toString();
} }
public ClassLoader getClassLoader() { public ClassLoader getClassLoader() {
synchronized (this) { synchronized (this) {
if (mClassLoader != null) { if (mClassLoader != null) {
@@ -428,7 +431,7 @@ public final class ActivityThread {
if ((mSharedLibraries != null) || if ((mSharedLibraries != null) ||
(instrumentationLibs != null)) { (instrumentationLibs != null)) {
zip = zip =
combineLibs(mSharedLibraries, instrumentationLibs) combineLibs(mSharedLibraries, instrumentationLibs)
+ ':' + zip; + ':' + zip;
} }
@@ -485,9 +488,9 @@ public final class ActivityThread {
if (mApplication != null) { if (mApplication != null) {
return mApplication; return mApplication;
} }
Application app = null; Application app = null;
String appClass = mApplicationInfo.className; String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) { if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application"; appClass = "android.app.Application";
@@ -510,7 +513,7 @@ public final class ActivityThread {
mActivityThread.mAllApplications.add(app); mActivityThread.mAllApplications.add(app);
return mApplication = app; return mApplication = app;
} }
public void removeContextRegistrations(Context context, public void removeContextRegistrations(Context context,
String who, String what) { String who, String what) {
HashMap<BroadcastReceiver, ReceiverDispatcher> rmap = HashMap<BroadcastReceiver, ReceiverDispatcher> rmap =
@@ -643,7 +646,7 @@ public final class ActivityThread {
final static class InnerReceiver extends IIntentReceiver.Stub { final static class InnerReceiver extends IIntentReceiver.Stub {
final WeakReference<ReceiverDispatcher> mDispatcher; final WeakReference<ReceiverDispatcher> mDispatcher;
final ReceiverDispatcher mStrongRef; final ReceiverDispatcher mStrongRef;
InnerReceiver(ReceiverDispatcher rd, boolean strong) { InnerReceiver(ReceiverDispatcher rd, boolean strong) {
mDispatcher = new WeakReference<ReceiverDispatcher>(rd); mDispatcher = new WeakReference<ReceiverDispatcher>(rd);
mStrongRef = strong ? rd : null; mStrongRef = strong ? rd : null;
@@ -661,7 +664,7 @@ public final class ActivityThread {
} }
} }
} }
final IIntentReceiver.Stub mIIntentReceiver; final IIntentReceiver.Stub mIIntentReceiver;
final BroadcastReceiver mReceiver; final BroadcastReceiver mReceiver;
final Context mContext; final Context mContext;
@@ -770,7 +773,7 @@ public final class ActivityThread {
BroadcastReceiver getIntentReceiver() { BroadcastReceiver getIntentReceiver() {
return mReceiver; return mReceiver;
} }
IIntentReceiver getIIntentReceiver() { IIntentReceiver getIIntentReceiver() {
return mIIntentReceiver; return mIIntentReceiver;
} }
@@ -901,7 +904,7 @@ public final class ActivityThread {
private static class InnerConnection extends IServiceConnection.Stub { private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference<ServiceDispatcher> mDispatcher; final WeakReference<ServiceDispatcher> mDispatcher;
InnerConnection(ServiceDispatcher sd) { InnerConnection(ServiceDispatcher sd) {
mDispatcher = new WeakReference<ServiceDispatcher>(sd); mDispatcher = new WeakReference<ServiceDispatcher>(sd);
} }
@@ -913,7 +916,7 @@ public final class ActivityThread {
} }
} }
} }
private final HashMap<ComponentName, ConnectionInfo> mActiveConnections private final HashMap<ComponentName, ConnectionInfo> mActiveConnections
= new HashMap<ComponentName, ConnectionInfo>(); = new HashMap<ComponentName, ConnectionInfo>();
@@ -965,7 +968,7 @@ public final class ActivityThread {
IServiceConnection getIServiceConnection() { IServiceConnection getIServiceConnection() {
return mIServiceConnection; return mIServiceConnection;
} }
int getFlags() { int getFlags() {
return mFlags; return mFlags;
} }
@@ -1191,7 +1194,7 @@ public final class ActivityThread {
+ " mode=" + backupMode + "}"; + " mode=" + backupMode + "}";
} }
} }
private static final class CreateServiceData { private static final class CreateServiceData {
IBinder token; IBinder token;
ServiceInfo info; ServiceInfo info;
@@ -1271,10 +1274,10 @@ public final class ActivityThread {
private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s"; private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
private static final String ONE_COUNT_COLUMN = "%17s %8d"; private static final String ONE_COUNT_COLUMN = "%17s %8d";
private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d"; private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d";
// Formatting for checkin service - update version if row format changes // Formatting for checkin service - update version if row format changes
private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1; private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1;
public final void schedulePauseActivity(IBinder token, boolean finished, public final void schedulePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges) { boolean userLeaving, int configChanges) {
queueOrSendMessage( queueOrSendMessage(
@@ -1343,7 +1346,7 @@ public final class ActivityThread {
synchronized (mRelaunchingActivities) { synchronized (mRelaunchingActivities) {
mRelaunchingActivities.add(r); mRelaunchingActivities.add(r);
} }
queueOrSendMessage(H.RELAUNCH_ACTIVITY, r, configChanges); queueOrSendMessage(H.RELAUNCH_ACTIVITY, r, configChanges);
} }
@@ -1514,7 +1517,7 @@ public final class ActivityThread {
throws RemoteException { throws RemoteException {
receiver.performReceive(intent, resultCode, dataStr, extras, ordered); receiver.performReceive(intent, resultCode, dataStr, extras, ordered);
} }
public void scheduleLowMemory() { public void scheduleLowMemory() {
queueOrSendMessage(H.LOW_MEMORY, null); queueOrSendMessage(H.LOW_MEMORY, null);
} }
@@ -1530,7 +1533,7 @@ public final class ActivityThread {
} catch (RemoteException e) { } catch (RemoteException e) {
} }
} }
public void profilerControl(boolean start, String path, ParcelFileDescriptor fd) { public void profilerControl(boolean start, String path, ParcelFileDescriptor fd) {
ProfilerControlData pcd = new ProfilerControlData(); ProfilerControlData pcd = new ProfilerControlData();
pcd.path = path; pcd.path = path;
@@ -1549,11 +1552,11 @@ public final class ActivityThread {
Log.w(TAG, "Failed setting process group to " + group, e); Log.w(TAG, "Failed setting process group to " + group, e);
} }
} }
public void getMemoryInfo(Debug.MemoryInfo outInfo) { public void getMemoryInfo(Debug.MemoryInfo outInfo) {
Debug.getMemoryInfo(outInfo); Debug.getMemoryInfo(outInfo);
} }
@Override @Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
long nativeMax = Debug.getNativeHeapSize() / 1024; long nativeMax = Debug.getNativeHeapSize() / 1024;
@@ -1589,7 +1592,7 @@ public final class ActivityThread {
long sqliteAllocated = SQLiteDebug.getHeapAllocatedSize() / 1024; long sqliteAllocated = SQLiteDebug.getHeapAllocatedSize() / 1024;
SQLiteDebug.PagerStats stats = new SQLiteDebug.PagerStats(); SQLiteDebug.PagerStats stats = new SQLiteDebug.PagerStats();
SQLiteDebug.getPagerStats(stats); SQLiteDebug.getPagerStats(stats);
// Check to see if we were called by checkin server. If so, print terse format. // Check to see if we were called by checkin server. If so, print terse format.
boolean doCheckinFormat = false; boolean doCheckinFormat = false;
if (args != null) { if (args != null) {
@@ -1597,79 +1600,79 @@ public final class ActivityThread {
if ("-c".equals(arg)) doCheckinFormat = true; if ("-c".equals(arg)) doCheckinFormat = true;
} }
} }
// For checkin, we print one long comma-separated list of values // For checkin, we print one long comma-separated list of values
if (doCheckinFormat) { if (doCheckinFormat) {
// NOTE: if you change anything significant below, also consider changing // NOTE: if you change anything significant below, also consider changing
// ACTIVITY_THREAD_CHECKIN_VERSION. // ACTIVITY_THREAD_CHECKIN_VERSION.
String processName = (mBoundApplication != null) String processName = (mBoundApplication != null)
? mBoundApplication.processName : "unknown"; ? mBoundApplication.processName : "unknown";
// Header // Header
pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(','); pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(',');
pw.print(Process.myPid()); pw.print(','); pw.print(Process.myPid()); pw.print(',');
pw.print(processName); pw.print(','); pw.print(processName); pw.print(',');
// Heap info - max // Heap info - max
pw.print(nativeMax); pw.print(','); pw.print(nativeMax); pw.print(',');
pw.print(dalvikMax); pw.print(','); pw.print(dalvikMax); pw.print(',');
pw.print("N/A,"); pw.print("N/A,");
pw.print(nativeMax + dalvikMax); pw.print(','); pw.print(nativeMax + dalvikMax); pw.print(',');
// Heap info - allocated // Heap info - allocated
pw.print(nativeAllocated); pw.print(','); pw.print(nativeAllocated); pw.print(',');
pw.print(dalvikAllocated); pw.print(','); pw.print(dalvikAllocated); pw.print(',');
pw.print("N/A,"); pw.print("N/A,");
pw.print(nativeAllocated + dalvikAllocated); pw.print(','); pw.print(nativeAllocated + dalvikAllocated); pw.print(',');
// Heap info - free // Heap info - free
pw.print(nativeFree); pw.print(','); pw.print(nativeFree); pw.print(',');
pw.print(dalvikFree); pw.print(','); pw.print(dalvikFree); pw.print(',');
pw.print("N/A,"); pw.print("N/A,");
pw.print(nativeFree + dalvikFree); pw.print(','); pw.print(nativeFree + dalvikFree); pw.print(',');
// Heap info - proportional set size // Heap info - proportional set size
pw.print(memInfo.nativePss); pw.print(','); pw.print(memInfo.nativePss); pw.print(',');
pw.print(memInfo.dalvikPss); pw.print(','); pw.print(memInfo.dalvikPss); pw.print(',');
pw.print(memInfo.otherPss); pw.print(','); pw.print(memInfo.otherPss); pw.print(',');
pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(','); pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(',');
// Heap info - shared // Heap info - shared
pw.print(nativeShared); pw.print(','); pw.print(nativeShared); pw.print(',');
pw.print(dalvikShared); pw.print(','); pw.print(dalvikShared); pw.print(',');
pw.print(otherShared); pw.print(','); pw.print(otherShared); pw.print(',');
pw.print(nativeShared + dalvikShared + otherShared); pw.print(','); pw.print(nativeShared + dalvikShared + otherShared); pw.print(',');
// Heap info - private // Heap info - private
pw.print(nativePrivate); pw.print(','); pw.print(nativePrivate); pw.print(',');
pw.print(dalvikPrivate); pw.print(','); pw.print(dalvikPrivate); pw.print(',');
pw.print(otherPrivate); pw.print(','); pw.print(otherPrivate); pw.print(',');
pw.print(nativePrivate + dalvikPrivate + otherPrivate); pw.print(','); pw.print(nativePrivate + dalvikPrivate + otherPrivate); pw.print(',');
// Object counts // Object counts
pw.print(viewInstanceCount); pw.print(','); pw.print(viewInstanceCount); pw.print(',');
pw.print(viewRootInstanceCount); pw.print(','); pw.print(viewRootInstanceCount); pw.print(',');
pw.print(appContextInstanceCount); pw.print(','); pw.print(appContextInstanceCount); pw.print(',');
pw.print(activityInstanceCount); pw.print(','); pw.print(activityInstanceCount); pw.print(',');
pw.print(globalAssetCount); pw.print(','); pw.print(globalAssetCount); pw.print(',');
pw.print(globalAssetManagerCount); pw.print(','); pw.print(globalAssetManagerCount); pw.print(',');
pw.print(binderLocalObjectCount); pw.print(','); pw.print(binderLocalObjectCount); pw.print(',');
pw.print(binderProxyObjectCount); pw.print(','); pw.print(binderProxyObjectCount); pw.print(',');
pw.print(binderDeathObjectCount); pw.print(','); pw.print(binderDeathObjectCount); pw.print(',');
pw.print(openSslSocketCount); pw.print(','); pw.print(openSslSocketCount); pw.print(',');
// SQL // SQL
pw.print(sqliteAllocated); pw.print(','); pw.print(sqliteAllocated); pw.print(',');
pw.print(stats.databaseBytes / 1024); pw.print(','); pw.print(stats.databaseBytes / 1024); pw.print(',');
pw.print(stats.numPagers); pw.print(','); pw.print(stats.numPagers); pw.print(',');
pw.print((stats.totalBytes - stats.referencedBytes) / 1024); pw.print(','); pw.print((stats.totalBytes - stats.referencedBytes) / 1024); pw.print(',');
pw.print(stats.referencedBytes / 1024); pw.print('\n'); pw.print(stats.referencedBytes / 1024); pw.print('\n');
return; return;
} }
// otherwise, show human-readable format // otherwise, show human-readable format
printRow(pw, HEAP_COLUMN, "", "native", "dalvik", "other", "total"); printRow(pw, HEAP_COLUMN, "", "native", "dalvik", "other", "total");
printRow(pw, HEAP_COLUMN, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax); printRow(pw, HEAP_COLUMN, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax);
@@ -1702,7 +1705,7 @@ public final class ActivityThread {
printRow(pw, ONE_COUNT_COLUMN, "Death Recipients:", binderDeathObjectCount); printRow(pw, ONE_COUNT_COLUMN, "Death Recipients:", binderDeathObjectCount);
printRow(pw, ONE_COUNT_COLUMN, "OpenSSL Sockets:", openSslSocketCount); printRow(pw, ONE_COUNT_COLUMN, "OpenSSL Sockets:", openSslSocketCount);
// SQLite mem info // SQLite mem info
pw.println(" "); pw.println(" ");
pw.println(" SQL"); pw.println(" SQL");
@@ -1711,7 +1714,7 @@ public final class ActivityThread {
printRow(pw, TWO_COUNT_COLUMNS, "numPagers:", stats.numPagers, "inactivePageKB:", printRow(pw, TWO_COUNT_COLUMNS, "numPagers:", stats.numPagers, "inactivePageKB:",
(stats.totalBytes - stats.referencedBytes) / 1024); (stats.totalBytes - stats.referencedBytes) / 1024);
printRow(pw, ONE_COUNT_COLUMN, "activePageKB:", stats.referencedBytes / 1024); printRow(pw, ONE_COUNT_COLUMN, "activePageKB:", stats.referencedBytes / 1024);
// Asset details. // Asset details.
String assetAlloc = AssetManager.getAssetAllocations(); String assetAlloc = AssetManager.getAssetAllocations();
if (assetAlloc != null) { if (assetAlloc != null) {
@@ -1727,6 +1730,10 @@ public final class ActivityThread {
} }
private final class H extends Handler { private final class H extends Handler {
private H() {
SamplingProfiler.getInstance().setEventThread(mLooper.getThread());
}
public static final int LAUNCH_ACTIVITY = 100; public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101; public static final int PAUSE_ACTIVITY = 101;
public static final int PAUSE_ACTIVITY_FINISHING= 102; public static final int PAUSE_ACTIVITY_FINISHING= 102;
@@ -1811,6 +1818,7 @@ public final class ActivityThread {
} break; } break;
case PAUSE_ACTIVITY: case PAUSE_ACTIVITY:
handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2); handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
maybeSnapshot();
break; break;
case PAUSE_ACTIVITY_FINISHING: case PAUSE_ACTIVITY_FINISHING:
handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2); handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);
@@ -1853,6 +1861,7 @@ public final class ActivityThread {
break; break;
case RECEIVER: case RECEIVER:
handleReceiver((ReceiverData)msg.obj); handleReceiver((ReceiverData)msg.obj);
maybeSnapshot();
break; break;
case CREATE_SERVICE: case CREATE_SERVICE:
handleCreateService((CreateServiceData)msg.obj); handleCreateService((CreateServiceData)msg.obj);
@@ -1868,6 +1877,7 @@ public final class ActivityThread {
break; break;
case STOP_SERVICE: case STOP_SERVICE:
handleStopService((IBinder)msg.obj); handleStopService((IBinder)msg.obj);
maybeSnapshot();
break; break;
case REQUEST_THUMBNAIL: case REQUEST_THUMBNAIL:
handleRequestThumbnail((IBinder)msg.obj); handleRequestThumbnail((IBinder)msg.obj);
@@ -1907,6 +1917,13 @@ public final class ActivityThread {
break; break;
} }
} }
void maybeSnapshot() {
if (mBoundApplication != null) {
SamplingProfilerIntegration.writeSnapshot(
mBoundApplication.processName);
}
}
} }
private final class Idler implements MessageQueue.IdleHandler { private final class Idler implements MessageQueue.IdleHandler {
@@ -1947,13 +1964,13 @@ public final class ActivityThread {
final private String mResDir; final private String mResDir;
final private float mScale; final private float mScale;
final private int mHash; final private int mHash;
ResourcesKey(String resDir, float scale) { ResourcesKey(String resDir, float scale) {
mResDir = resDir; mResDir = resDir;
mScale = scale; mScale = scale;
mHash = mResDir.hashCode() << 2 + (int) (mScale * 2); mHash = mResDir.hashCode() << 2 + (int) (mScale * 2);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return mHash; return mHash;
@@ -2004,7 +2021,7 @@ public final class ActivityThread {
final ArrayList<ActivityRecord> mRelaunchingActivities final ArrayList<ActivityRecord> mRelaunchingActivities
= new ArrayList<ActivityRecord>(); = new ArrayList<ActivityRecord>();
Configuration mPendingConfiguration = null; Configuration mPendingConfiguration = null;
// These can be accessed by multiple threads; mPackages is the lock. // These can be accessed by multiple threads; mPackages is the lock.
// XXX For now we keep around information about all packages we have // XXX For now we keep around information about all packages we have
// seen, not removing entries from this map. // seen, not removing entries from this map.
@@ -2139,7 +2156,7 @@ public final class ActivityThread {
return false; return false;
} }
} }
ActivityThread() { ActivityThread() {
} }
@@ -2172,11 +2189,11 @@ public final class ActivityThread {
public Application getApplication() { public Application getApplication() {
return mInitialApplication; return mInitialApplication;
} }
public String getProcessName() { public String getProcessName() {
return mBoundApplication.processName; return mBoundApplication.processName;
} }
public ApplicationContext getSystemContext() { public ApplicationContext getSystemContext() {
synchronized (this) { synchronized (this) {
if (mSystemContext == null) { if (mSystemContext == null) {
@@ -2231,7 +2248,7 @@ public final class ActivityThread {
} }
return aInfo; return aInfo;
} }
public final Activity startActivityNow(Activity parent, String id, public final Activity startActivityNow(Activity parent, String id,
Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state, Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
Object lastNonConfigurationInstance) { Object lastNonConfigurationInstance) {
@@ -2314,7 +2331,7 @@ public final class ActivityThread {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.packageInfo = getPackageInfo(aInfo.applicationInfo,
Context.CONTEXT_INCLUDE_CODE); Context.CONTEXT_INCLUDE_CODE);
} }
ComponentName component = r.intent.getComponent(); ComponentName component = r.intent.getComponent();
if (component == null) { if (component == null) {
component = r.intent.resolveActivity( component = r.intent.resolveActivity(
@@ -2346,7 +2363,7 @@ public final class ActivityThread {
try { try {
Application app = r.packageInfo.makeApplication(false); Application app = r.packageInfo.makeApplication(false);
if (localLOGV) Log.v(TAG, "Performing launch of " + r); if (localLOGV) Log.v(TAG, "Performing launch of " + r);
if (localLOGV) Log.v( if (localLOGV) Log.v(
TAG, r + ": app=" + app TAG, r + ": app=" + app
@@ -2365,7 +2382,7 @@ public final class ActivityThread {
r.ident, app, r.intent, r.activityInfo, title, r.parent, r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstance, r.embeddedID, r.lastNonConfigurationInstance,
r.lastNonConfigurationChildInstances, config); r.lastNonConfigurationChildInstances, config);
if (customIntent != null) { if (customIntent != null) {
activity.mIntent = customIntent; activity.mIntent = customIntent;
} }
@@ -2503,7 +2520,7 @@ public final class ActivityThread {
} }
} }
} }
private final void handleNewIntent(NewIntentData data) { private final void handleNewIntent(NewIntentData data) {
performNewIntents(data.token, data.intents); performNewIntents(data.token, data.intents);
} }
@@ -2541,7 +2558,7 @@ public final class ActivityThread {
try { try {
Application app = packageInfo.makeApplication(false); Application app = packageInfo.makeApplication(false);
if (localLOGV) Log.v( if (localLOGV) Log.v(
TAG, "Performing receive of " + data.intent TAG, "Performing receive of " + data.intent
+ ": app=" + app + ": app=" + app
@@ -2598,7 +2615,7 @@ public final class ActivityThread {
+ " already exists"); + " already exists");
return; return;
} }
BackupAgent agent = null; BackupAgent agent = null;
String classname = data.appInfo.backupAgentName; String classname = data.appInfo.backupAgentName;
if (classname == null) { if (classname == null) {
@@ -2652,7 +2669,7 @@ public final class ActivityThread {
// Tear down a BackupAgent // Tear down a BackupAgent
private final void handleDestroyBackupAgent(CreateBackupAgentData data) { private final void handleDestroyBackupAgent(CreateBackupAgentData data) {
if (DEBUG_BACKUP) Log.v(TAG, "handleDestroyBackupAgent: " + data); if (DEBUG_BACKUP) Log.v(TAG, "handleDestroyBackupAgent: " + data);
PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo); PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo);
String packageName = packageInfo.mPackageName; String packageName = packageInfo.mPackageName;
BackupAgent agent = mBackupAgents.get(packageName); BackupAgent agent = mBackupAgents.get(packageName);
@@ -2857,9 +2874,9 @@ public final class ActivityThread {
} }
r.activity.performResume(); r.activity.performResume();
EventLog.writeEvent(LOG_ON_RESUME_CALLED, EventLog.writeEvent(LOG_ON_RESUME_CALLED,
r.activity.getComponentName().getClassName()); r.activity.getComponentName().getClassName());
r.paused = false; r.paused = false;
r.stopped = false; r.stopped = false;
if (r.activity.mStartedActivity) { if (r.activity.mStartedActivity) {
@@ -2895,7 +2912,7 @@ public final class ActivityThread {
final int forwardBit = isForward ? final int forwardBit = isForward ?
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0; WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
// If the window hasn't yet been added to the window manager, // If the window hasn't yet been added to the window manager,
// and this guy didn't finish itself or start another activity, // and this guy didn't finish itself or start another activity,
// then go ahead and add the window. // then go ahead and add the window.
@@ -3014,7 +3031,7 @@ public final class ActivityThread {
if (userLeaving) { if (userLeaving) {
performUserLeavingActivity(r); performUserLeavingActivity(r);
} }
r.activity.mConfigChangeFlags |= configChanges; r.activity.mConfigChangeFlags |= configChanges;
Bundle state = performPauseActivity(token, finished, true); Bundle state = performPauseActivity(token, finished, true);
@@ -3191,7 +3208,7 @@ public final class ActivityThread {
+ " win=" + r.window); + " win=" + r.window);
updateVisibility(r, show); updateVisibility(r, show);
// Tell activity manager we have been stopped. // Tell activity manager we have been stopped.
try { try {
ActivityManagerNative.getDefault().activityStopped( ActivityManagerNative.getDefault().activityStopped(
@@ -3307,7 +3324,7 @@ public final class ActivityThread {
try { try {
r.activity.mCalled = false; r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity); mInstrumentation.callActivityOnPause(r.activity);
EventLog.writeEvent(LOG_ON_PAUSE_CALLED, EventLog.writeEvent(LOG_ON_PAUSE_CALLED,
r.activity.getComponentName().getClassName()); r.activity.getComponentName().getClassName());
if (!r.activity.mCalled) { if (!r.activity.mCalled) {
throw new SuperNotCalledException( throw new SuperNotCalledException(
@@ -3364,7 +3381,7 @@ public final class ActivityThread {
+ ": " + e.toString(), e); + ": " + e.toString(), e);
} }
} }
} }
try { try {
r.activity.mCalled = false; r.activity.mCalled = false;
@@ -3446,7 +3463,7 @@ public final class ActivityThread {
unscheduleGcIdler(); unscheduleGcIdler();
Configuration changedConfig = null; Configuration changedConfig = null;
// First: make sure we have the most recent configuration and most // First: make sure we have the most recent configuration and most
// recent version of the activity, or skip it if some previous call // recent version of the activity, or skip it if some previous call
// had taken a more recent version. // had taken a more recent version.
@@ -3463,38 +3480,38 @@ public final class ActivityThread {
N--; N--;
} }
} }
if (tmp == null) { if (tmp == null) {
return; return;
} }
if (mPendingConfiguration != null) { if (mPendingConfiguration != null) {
changedConfig = mPendingConfiguration; changedConfig = mPendingConfiguration;
mPendingConfiguration = null; mPendingConfiguration = null;
} }
} }
// If there was a pending configuration change, execute it first. // If there was a pending configuration change, execute it first.
if (changedConfig != null) { if (changedConfig != null) {
handleConfigurationChanged(changedConfig); handleConfigurationChanged(changedConfig);
} }
ActivityRecord r = mActivities.get(tmp.token); ActivityRecord r = mActivities.get(tmp.token);
if (localLOGV) Log.v(TAG, "Handling relaunch of " + r); if (localLOGV) Log.v(TAG, "Handling relaunch of " + r);
if (r == null) { if (r == null) {
return; return;
} }
r.activity.mConfigChangeFlags |= configChanges; r.activity.mConfigChangeFlags |= configChanges;
Intent currentIntent = r.activity.mIntent; Intent currentIntent = r.activity.mIntent;
Bundle savedState = null; Bundle savedState = null;
if (!r.paused) { if (!r.paused) {
savedState = performPauseActivity(r.token, false, true); savedState = performPauseActivity(r.token, false, true);
} }
handleDestroyActivity(r.token, false, configChanges, true); handleDestroyActivity(r.token, false, configChanges, true);
r.activity = null; r.activity = null;
r.window = null; r.window = null;
r.hideForNow = false; r.hideForNow = false;
@@ -3518,7 +3535,7 @@ public final class ActivityThread {
if (savedState != null) { if (savedState != null) {
r.state = savedState; r.state = savedState;
} }
handleLaunchActivity(r, currentIntent); handleLaunchActivity(r, currentIntent);
} }
@@ -3548,7 +3565,7 @@ public final class ActivityThread {
boolean allActivities, Configuration newConfig) { boolean allActivities, Configuration newConfig) {
ArrayList<ComponentCallbacks> callbacks ArrayList<ComponentCallbacks> callbacks
= new ArrayList<ComponentCallbacks>(); = new ArrayList<ComponentCallbacks>();
if (mActivities.size() > 0) { if (mActivities.size() > 0) {
Iterator<ActivityRecord> it = mActivities.values().iterator(); Iterator<ActivityRecord> it = mActivities.values().iterator();
while (it.hasNext()) { while (it.hasNext()) {
@@ -3589,10 +3606,10 @@ public final class ActivityThread {
for (int i=0; i<N; i++) { for (int i=0; i<N; i++) {
callbacks.add(mAllApplications.get(i)); callbacks.add(mAllApplications.get(i));
} }
return callbacks; return callbacks;
} }
private final void performConfigurationChanged( private final void performConfigurationChanged(
ComponentCallbacks cb, Configuration config) { ComponentCallbacks cb, Configuration config) {
// Only for Activity objects, check that they actually call up to their // Only for Activity objects, check that they actually call up to their
@@ -3602,18 +3619,18 @@ public final class ActivityThread {
if (activity != null) { if (activity != null) {
activity.mCalled = false; activity.mCalled = false;
} }
boolean shouldChangeConfig = false; boolean shouldChangeConfig = false;
if ((activity == null) || (activity.mCurrentConfig == null)) { if ((activity == null) || (activity.mCurrentConfig == null)) {
shouldChangeConfig = true; shouldChangeConfig = true;
} else { } else {
// If the new config is the same as the config this Activity // If the new config is the same as the config this Activity
// is already running with then don't bother calling // is already running with then don't bother calling
// onConfigurationChanged // onConfigurationChanged
int diff = activity.mCurrentConfig.diff(config); int diff = activity.mCurrentConfig.diff(config);
if (diff != 0) { if (diff != 0) {
// If this activity doesn't handle any of the config changes // If this activity doesn't handle any of the config changes
// then don't bother calling onConfigurationChanged as we're // then don't bother calling onConfigurationChanged as we're
// going to destroy it. // going to destroy it.
@@ -3622,10 +3639,10 @@ public final class ActivityThread {
} }
} }
} }
if (shouldChangeConfig) { if (shouldChangeConfig) {
cb.onConfigurationChanged(config); cb.onConfigurationChanged(config);
if (activity != null) { if (activity != null) {
if (!activity.mCalled) { if (!activity.mCalled) {
throw new SuperNotCalledException( throw new SuperNotCalledException(
@@ -3639,17 +3656,17 @@ public final class ActivityThread {
} }
final void handleConfigurationChanged(Configuration config) { final void handleConfigurationChanged(Configuration config) {
synchronized (mRelaunchingActivities) { synchronized (mRelaunchingActivities) {
if (mPendingConfiguration != null) { if (mPendingConfiguration != null) {
config = mPendingConfiguration; config = mPendingConfiguration;
mPendingConfiguration = null; mPendingConfiguration = null;
} }
} }
ArrayList<ComponentCallbacks> callbacks ArrayList<ComponentCallbacks> callbacks
= new ArrayList<ComponentCallbacks>(); = new ArrayList<ComponentCallbacks>();
synchronized(mPackages) { synchronized(mPackages) {
if (mConfiguration == null) { if (mConfiguration == null) {
mConfiguration = new Configuration(); mConfiguration = new Configuration();
@@ -3684,10 +3701,10 @@ public final class ActivityThread {
} }
} }
} }
callbacks = collectComponentCallbacksLocked(false, config); callbacks = collectComponentCallbacksLocked(false, config);
} }
final int N = callbacks.size(); final int N = callbacks.size();
for (int i=0; i<N; i++) { for (int i=0; i<N; i++) {
performConfigurationChanged(callbacks.get(i), config); performConfigurationChanged(callbacks.get(i), config);
@@ -3699,7 +3716,7 @@ public final class ActivityThread {
if (r == null || r.activity == null) { if (r == null || r.activity == null) {
return; return;
} }
performConfigurationChanged(r.activity, mConfiguration); performConfigurationChanged(r.activity, mConfiguration);
} }
@@ -3722,7 +3739,7 @@ public final class ActivityThread {
Debug.stopMethodTracing(); Debug.stopMethodTracing();
} }
} }
final void handleLowMemory() { final void handleLowMemory() {
ArrayList<ComponentCallbacks> callbacks ArrayList<ComponentCallbacks> callbacks
= new ArrayList<ComponentCallbacks>(); = new ArrayList<ComponentCallbacks>();
@@ -3730,7 +3747,7 @@ public final class ActivityThread {
synchronized(mPackages) { synchronized(mPackages) {
callbacks = collectComponentCallbacksLocked(true, null); callbacks = collectComponentCallbacksLocked(true, null);
} }
final int N = callbacks.size(); final int N = callbacks.size();
for (int i=0; i<N; i++) { for (int i=0; i<N; i++) {
callbacks.get(i).onLowMemory(); callbacks.get(i).onLowMemory();
@@ -3741,7 +3758,7 @@ public final class ActivityThread {
int sqliteReleased = SQLiteDatabase.releaseMemory(); int sqliteReleased = SQLiteDatabase.releaseMemory();
EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased); EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
} }
// Ask graphics to free up as much as possible (font/image caches) // Ask graphics to free up as much as possible (font/image caches)
Canvas.freeCaches(); Canvas.freeCaches();
@@ -3788,7 +3805,7 @@ public final class ActivityThread {
== 0) { == 0) {
Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT); Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
} }
if (data.debugMode != IApplicationThread.DEBUG_OFF) { if (data.debugMode != IApplicationThread.DEBUG_OFF) {
// XXX should have option to change the port. // XXX should have option to change the port.
Debug.changeDebugPort(8100); Debug.changeDebugPort(8100);
@@ -4213,6 +4230,8 @@ public final class ActivityThread {
} }
public static final void main(String[] args) { public static final void main(String[] args) {
SamplingProfilerIntegration.start();
Process.setArgV0("<pre-initialized>"); Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper(); Looper.prepareMainLooper();
@@ -4228,8 +4247,11 @@ public final class ActivityThread {
thread.detach(); thread.detach();
String name; String name;
if (thread.mInitialApplication != null) name = thread.mInitialApplication.getPackageName(); if (thread.mInitialApplication != null) {
else name = "<unknown>"; name = thread.mInitialApplication.getPackageName();
} else {
name = "<unknown>";
}
Log.i(TAG, "Main thread of " + name + " is now exiting"); Log.i(TAG, "Main thread of " + name + " is now exiting");
} }
} }

View File

@@ -83,7 +83,7 @@ public class RuntimeInit {
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler()); Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
int hasQwerty = getQwertyKeyboard(); int hasQwerty = getQwertyKeyboard();
if (Config.LOGV) Log.d(TAG, ">>>>> qwerty keyboard = " + hasQwerty); if (Config.LOGV) Log.d(TAG, ">>>>> qwerty keyboard = " + hasQwerty);
if (hasQwerty == 1) { if (hasQwerty == 1) {
System.setProperty("qwerty", "1"); System.setProperty("qwerty", "1");
@@ -133,13 +133,13 @@ public class RuntimeInit {
* @param className Fully-qualified class name * @param className Fully-qualified class name
* @param argv Argument vector for main() * @param argv Argument vector for main()
*/ */
private static void invokeStaticMain(String className, String[] argv) private static void invokeStaticMain(String className, String[] argv)
throws ZygoteInit.MethodAndArgsCaller { throws ZygoteInit.MethodAndArgsCaller {
// We want to be fairly aggressive about heap utilization, to avoid // We want to be fairly aggressive about heap utilization, to avoid
// holding on to a lot of memory that isn't needed. // holding on to a lot of memory that isn't needed.
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f); VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
Class<?> cl; Class<?> cl;
try { try {
@@ -178,7 +178,7 @@ public class RuntimeInit {
public static final void main(String[] argv) { public static final void main(String[] argv) {
commonInit(); commonInit();
/* /*
* Now that we're running in interpreted code, call back into native code * Now that we're running in interpreted code, call back into native code
* to run the system. * to run the system.
@@ -187,7 +187,7 @@ public class RuntimeInit {
if (Config.LOGV) Log.d(TAG, "Leaving RuntimeInit!"); if (Config.LOGV) Log.d(TAG, "Leaving RuntimeInit!");
} }
public static final native void finishInit(); public static final native void finishInit();
/** /**
@@ -236,7 +236,7 @@ public class RuntimeInit {
} }
// Remaining arguments are passed to the start class's static main // Remaining arguments are passed to the start class's static main
String startClass = argv[curArg++]; String startClass = argv[curArg++];
String[] startArgs = new String[argv.length - curArg]; String[] startArgs = new String[argv.length - curArg];
@@ -245,28 +245,28 @@ public class RuntimeInit {
} }
public static final native void zygoteInitNative(); public static final native void zygoteInitNative();
/** /**
* Returns 1 if the computer is on. If the computer isn't on, the value returned by this method is undefined. * Returns 1 if the computer is on. If the computer isn't on, the value returned by this method is undefined.
*/ */
public static final native int isComputerOn(); public static final native int isComputerOn();
/** /**
* Turns the computer on if the computer is off. If the computer is on, the behavior of this method is undefined. * Turns the computer on if the computer is off. If the computer is on, the behavior of this method is undefined.
*/ */
public static final native void turnComputerOn(); public static final native void turnComputerOn();
/** /**
* *
* @return 1 if the device has a qwerty keyboard * @return 1 if the device has a qwerty keyboard
*/ */
public static native int getQwertyKeyboard(); public static native int getQwertyKeyboard();
/** /**
* Report a fatal error in the current process. If this is a user-process, * Report a fatal error in the current process. If this is a user-process,
* a dialog may be displayed informing the user of the error. This * a dialog may be displayed informing the user of the error. This
* function does not return; it forces the current process to exit. * function does not return; it forces the current process to exit.
* *
* @param tag to use when logging the error * @param tag to use when logging the error
* @param t exception that was generated by the error * @param t exception that was generated by the error
*/ */
@@ -405,7 +405,7 @@ public class RuntimeInit {
/** /**
* Replay an encoded CrashData record back into a useable CrashData record. This can be * Replay an encoded CrashData record back into a useable CrashData record. This can be
* helpful for providing debugging output after a process error. * helpful for providing debugging output after a process error.
* *
* @param crashDataBytes The byte array containing the encoded crash record * @param crashDataBytes The byte array containing the encoded crash record
* @return new CrashData record, or null if could not create one. * @return new CrashData record, or null if could not create one.
*/ */

View File

@@ -0,0 +1,144 @@
package com.android.internal.os;
import dalvik.system.SamplingProfiler;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import android.util.Log;
import android.os.*;
import android.net.Uri;
/**
* Integrates the framework with Dalvik's sampling profiler.
*/
public class SamplingProfilerIntegration {
private static final String TAG = "SamplingProfilerIntegration";
private static final boolean enabled;
private static final Executor snapshotWriter;
static {
enabled = "1".equals(SystemProperties.get("persist.sampling_profiler"));
if (enabled) {
snapshotWriter = Executors.newSingleThreadExecutor();
Log.i(TAG, "Profiler is enabled.");
} else {
snapshotWriter = null;
Log.i(TAG, "Profiler is disabled.");
}
}
/**
* Is profiling enabled?
*/
public static boolean isEnabled() {
return enabled;
}
/**
* Starts the profiler if profiling is enabled.
*/
public static void start() {
if (!enabled) return;
SamplingProfiler.getInstance().start(10);
}
/** Whether or not we've created the snapshots dir. */
static boolean dirMade = false;
/** Whether or not a snapshot is being persisted. */
static volatile boolean pending;
/**
* Writes a snapshot to the SD card if profiling is enabled.
*/
public static void writeSnapshot(final String name) {
if (!enabled) return;
if (!pending) {
pending = true;
snapshotWriter.execute(new Runnable() {
public void run() {
String dir = "/sdcard/snapshots";
if (!dirMade) {
makeDirectory(dir);
dirMade = true;
}
try {
writeSnapshot(dir, name);
} finally {
pending = false;
}
}
});
}
}
/**
* Writes the zygote's snapshot to internal storage if profiling is enabled.
*/
public static void writeZygoteSnapshot() {
if (!enabled) return;
String dir = "/data/zygote/snapshots";
makeDirectory(dir);
writeSnapshot(dir, "zygote");
}
private static void writeSnapshot(String dir, String name) {
byte[] snapshot = SamplingProfiler.getInstance().snapshot();
if (snapshot == null) {
return;
}
/*
* We use the current time as a unique ID. We can't use a counter
* because processes restart. This could result in some overlap if
* we capture two snapshots in rapid succession.
*/
long start = System.currentTimeMillis();
String path = dir + "/" + name.replace(':', '.') + "-"
+ System.currentTimeMillis() + ".snapshot";
try {
// Try to open the file a few times. The SD card may not be mounted.
FileOutputStream out;
int count = 0;
while (true) {
try {
out = new FileOutputStream(path);
break;
} catch (FileNotFoundException e) {
if (++count > 3) {
Log.e(TAG, "Could not open " + path + ".");
return;
}
// Sleep for a bit and then try again.
try {
Thread.sleep(2500);
} catch (InterruptedException e1) { /* ignore */ }
}
}
try {
out.write(snapshot);
} finally {
out.close();
}
long elapsed = System.currentTimeMillis() - start;
Log.i(TAG, "Wrote snapshot for " + name
+ " in " + elapsed + "ms.");
} catch (IOException e) {
Log.e(TAG, "Error writing snapshot.", e);
}
}
private static void makeDirectory(String dir) {
new File(dir).mkdirs();
}
}

View File

@@ -19,7 +19,6 @@ package com.android.internal.os;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.LocalServerSocket; import android.net.LocalServerSocket;
import android.os.Debug; import android.os.Debug;
@@ -31,6 +30,7 @@ import android.util.Log;
import dalvik.system.VMRuntime; import dalvik.system.VMRuntime;
import dalvik.system.Zygote; import dalvik.system.Zygote;
import dalvik.system.SamplingProfiler;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.FileDescriptor; import java.io.FileDescriptor;
@@ -73,7 +73,7 @@ public class ZygoteInit {
* never gets destroyed. * never gets destroyed.
*/ */
private static Resources mResources; private static Resources mResources;
/** /**
* The number of times that the main Zygote loop * The number of times that the main Zygote loop
* should run before calling gc() again. * should run before calling gc() again.
@@ -192,7 +192,7 @@ public class ZygoteInit {
* RuntimeException on failure. * RuntimeException on failure.
*/ */
private static ZygoteConnection acceptCommandPeer() { private static ZygoteConnection acceptCommandPeer() {
try { try {
return new ZygoteConnection(sServerSocket.accept()); return new ZygoteConnection(sServerSocket.accept());
} catch (IOException ex) { } catch (IOException ex) {
throw new RuntimeException( throw new RuntimeException(
@@ -251,7 +251,7 @@ public class ZygoteInit {
*/ */
private static void preloadClasses() { private static void preloadClasses() {
final VMRuntime runtime = VMRuntime.getRuntime(); final VMRuntime runtime = VMRuntime.getRuntime();
InputStream is = ZygoteInit.class.getClassLoader().getResourceAsStream( InputStream is = ZygoteInit.class.getClassLoader().getResourceAsStream(
PRELOADED_CLASSES); PRELOADED_CLASSES);
if (is == null) { if (is == null) {
@@ -259,7 +259,7 @@ public class ZygoteInit {
} else { } else {
Log.i(TAG, "Preloading classes..."); Log.i(TAG, "Preloading classes...");
long startTime = SystemClock.uptimeMillis(); long startTime = SystemClock.uptimeMillis();
// Drop root perms while running static initializers. // Drop root perms while running static initializers.
setEffectiveGroup(UNPRIVILEGED_GID); setEffectiveGroup(UNPRIVILEGED_GID);
setEffectiveUser(UNPRIVILEGED_UID); setEffectiveUser(UNPRIVILEGED_UID);
@@ -275,7 +275,7 @@ public class ZygoteInit {
Debug.startAllocCounting(); Debug.startAllocCounting();
try { try {
BufferedReader br BufferedReader br
= new BufferedReader(new InputStreamReader(is), 256); = new BufferedReader(new InputStreamReader(is), 256);
int count = 0; int count = 0;
@@ -394,7 +394,7 @@ public class ZygoteInit {
*/ */
private static void preloadResources() { private static void preloadResources() {
final VMRuntime runtime = VMRuntime.getRuntime(); final VMRuntime runtime = VMRuntime.getRuntime();
Debug.startAllocCounting(); Debug.startAllocCounting();
try { try {
runtime.gcSoftReferences(); runtime.gcSoftReferences();
@@ -527,7 +527,7 @@ public class ZygoteInit {
/** /**
* Prepare the arguments and fork for the system server process. * Prepare the arguments and fork for the system server process.
*/ */
private static boolean startSystemServer() private static boolean startSystemServer()
throws MethodAndArgsCaller, RuntimeException { throws MethodAndArgsCaller, RuntimeException {
/* Hardcoded command line to start the system server */ /* Hardcoded command line to start the system server */
String args[] = { String args[] = {
@@ -561,8 +561,8 @@ public class ZygoteInit {
parsedArgs.gids, debugFlags, null); parsedArgs.gids, debugFlags, null);
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
throw new RuntimeException(ex); throw new RuntimeException(ex);
} }
/* For child process */ /* For child process */
if (pid == 0) { if (pid == 0) {
handleSystemServerProcess(parsedArgs); handleSystemServerProcess(parsedArgs);
@@ -573,6 +573,9 @@ public class ZygoteInit {
public static void main(String argv[]) { public static void main(String argv[]) {
try { try {
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
registerZygoteSocket(); registerZygoteSocket();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis()); SystemClock.uptimeMillis());
@@ -582,6 +585,13 @@ public class ZygoteInit {
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis()); SystemClock.uptimeMillis());
if (SamplingProfilerIntegration.isEnabled()) {
SamplingProfiler sp = SamplingProfiler.getInstance();
sp.pause();
SamplingProfilerIntegration.writeZygoteSnapshot();
sp.shutDown();
}
// Do an initial gc to clean up after startup // Do an initial gc to clean up after startup
gc(); gc();

View File

@@ -18,6 +18,7 @@ package com.android.server;
import com.android.server.am.ActivityManagerService; import com.android.server.am.ActivityManagerService;
import com.android.server.status.StatusBarService; import com.android.server.status.StatusBarService;
import com.android.internal.os.SamplingProfilerIntegration;
import dalvik.system.VMRuntime; import dalvik.system.VMRuntime;
@@ -41,6 +42,9 @@ import android.util.EventLog;
import android.util.Log; import android.util.Log;
import android.accounts.AccountManagerService; import android.accounts.AccountManagerService;
import java.util.Timer;
import java.util.TimerTask;
class ServerThread extends Thread { class ServerThread extends Thread {
private static final String TAG = "SystemServer"; private static final String TAG = "SystemServer";
private final static boolean INCLUDE_DEMO = false; private final static boolean INCLUDE_DEMO = false;
@@ -452,6 +456,9 @@ public class SystemServer
public static final int FACTORY_TEST_LOW_LEVEL = 1; public static final int FACTORY_TEST_LOW_LEVEL = 1;
public static final int FACTORY_TEST_HIGH_LEVEL = 2; public static final int FACTORY_TEST_HIGH_LEVEL = 2;
static Timer timer;
static final long SNAPSHOT_INTERVAL = 60 * 60 * 1000; // 1hr
/** /**
* This method is called from Zygote to initialize the system. This will cause the native * This method is called from Zygote to initialize the system. This will cause the native
* services (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call back * services (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call back
@@ -460,6 +467,17 @@ public class SystemServer
native public static void init1(String[] args); native public static void init1(String[] args);
public static void main(String[] args) { public static void main(String[] args) {
if (SamplingProfilerIntegration.isEnabled()) {
SamplingProfilerIntegration.start();
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
SamplingProfilerIntegration.writeSnapshot("system_server");
}
}, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
}
// The system server has to run all of the time, so it needs to be // The system server has to run all of the time, so it needs to be
// as efficient as possible with its memory usage. // as efficient as possible with its memory usage.
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);