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