diff options
Diffstat (limited to 'core/java/android/app/ActivityThread.java')
-rw-r--r-- | core/java/android/app/ActivityThread.java | 406 |
1 files changed, 264 insertions, 142 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index e045105..b116bf8 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); @@ -119,14 +122,15 @@ public final class ActivityThread { private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV; private static final boolean DEBUG_BROADCAST = false; private static final boolean DEBUG_RESULTS = false; - private static final boolean DEBUG_BACKUP = true; + private static final boolean DEBUG_BACKUP = false; + private static final boolean DEBUG_CONFIGURATION = false; private static final long MIN_TIME_BETWEEN_GCS = 5*1000; private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";"); private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003; 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(); } @@ -289,9 +293,9 @@ public final class ActivityThread { } public PackageInfo(ActivityThread activityThread, String name, - Context systemContext) { + Context systemContext, ApplicationInfo info) { mActivityThread = activityThread; - mApplicationInfo = new ApplicationInfo(); + mApplicationInfo = info != null ? info : new ApplicationInfo(); mApplicationInfo.packageName = name; mPackageName = name; mAppDir = null; @@ -314,7 +318,7 @@ public final class ActivityThread { public ApplicationInfo getApplicationInfo() { return mApplicationInfo; } - + public boolean isSecurityViolation() { return mSecurityViolation; } @@ -322,7 +326,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 +354,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 +382,7 @@ public final class ActivityThread { if (dupCheck && ArrayUtils.contains(list1, s)) { continue; } - + if (first) { first = false; } else { @@ -390,7 +394,7 @@ public final class ActivityThread { return result.toString(); } - + public ClassLoader getClassLoader() { synchronized (this) { if (mClassLoader != null) { @@ -428,7 +432,7 @@ public final class ActivityThread { if ((mSharedLibraries != null) || (instrumentationLibs != null)) { - zip = + zip = combineLibs(mSharedLibraries, instrumentationLibs) + ':' + zip; } @@ -481,13 +485,14 @@ public final class ActivityThread { return mResources; } - public Application makeApplication(boolean forceDefaultAppClass) { + public Application makeApplication(boolean forceDefaultAppClass, + Instrumentation instrumentation) { if (mApplication != null) { return mApplication; } - + Application app = null; - + String appClass = mApplicationInfo.className; if (forceDefaultAppClass || (appClass == null)) { appClass = "android.app.Application"; @@ -508,9 +513,23 @@ public final class ActivityThread { } } mActivityThread.mAllApplications.add(app); - return mApplication = app; + mApplication = app; + + if (instrumentation != null) { + try { + instrumentation.callApplicationOnCreate(app); + } catch (Exception e) { + if (!instrumentation.onException(app, e)) { + throw new RuntimeException( + "Unable to create application " + app.getClass().getName() + + ": " + e.toString(), e); + } + } + } + + return app; } - + public void removeContextRegistrations(Context context, String who, String what) { HashMap<BroadcastReceiver, ReceiverDispatcher> rmap = @@ -643,13 +662,13 @@ 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; } public void performReceive(Intent intent, int resultCode, - String data, Bundle extras, boolean ordered) { + String data, Bundle extras, boolean ordered, boolean sticky) { ReceiverDispatcher rd = mDispatcher.get(); if (DEBUG_BROADCAST) { int seq = intent.getIntExtra("seq", -1); @@ -657,11 +676,12 @@ public final class ActivityThread { + " to " + rd); } if (rd != null) { - rd.performReceive(intent, resultCode, data, extras, ordered); + rd.performReceive(intent, resultCode, data, extras, + ordered, sticky); } } } - + final IIntentReceiver.Stub mIIntentReceiver; final BroadcastReceiver mReceiver; final Context mContext; @@ -677,6 +697,7 @@ public final class ActivityThread { private String mCurData; private Bundle mCurMap; private boolean mCurOrdered; + private boolean mCurSticky; public void run() { BroadcastReceiver receiver = mReceiver; @@ -702,6 +723,7 @@ public final class ActivityThread { receiver.setResult(mCurCode, mCurData, mCurMap); receiver.clearAbortBroadcast(); receiver.setOrderedHint(mCurOrdered); + receiver.setInitialStickyHint(mCurSticky); receiver.onReceive(mContext, intent); } catch (Exception e) { if (mRegistered && mCurOrdered) { @@ -770,7 +792,7 @@ public final class ActivityThread { BroadcastReceiver getIntentReceiver() { return mReceiver; } - + IIntentReceiver getIIntentReceiver() { return mIIntentReceiver; } @@ -784,7 +806,7 @@ public final class ActivityThread { } public void performReceive(Intent intent, int resultCode, - String data, Bundle extras, boolean ordered) { + String data, Bundle extras, boolean ordered, boolean sticky) { if (DEBUG_BROADCAST) { int seq = intent.getIntExtra("seq", -1); Log.i(TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq @@ -796,6 +818,7 @@ public final class ActivityThread { args.mCurData = data; args.mCurMap = extras; args.mCurOrdered = ordered; + args.mCurSticky = sticky; if (!mActivityThread.post(args)) { if (mRegistered) { IActivityManager mgr = ActivityManagerNative.getDefault(); @@ -901,7 +924,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 +936,7 @@ public final class ActivityThread { } } } - + private final HashMap<ComponentName, ConnectionInfo> mActiveConnections = new HashMap<ComponentName, ConnectionInfo>(); @@ -965,7 +988,7 @@ public final class ActivityThread { IServiceConnection getIServiceConnection() { return mIServiceConnection; } - + int getFlags() { return mFlags; } @@ -1112,6 +1135,7 @@ public final class ActivityThread { boolean stopped; boolean hideForNow; Configuration newConfig; + Configuration createdConfig; ActivityRecord nextIdle; ActivityInfo activityInfo; @@ -1191,7 +1215,7 @@ public final class ActivityThread { + " mode=" + backupMode + "}"; } } - + private static final class CreateServiceData { IBinder token; ServiceInfo info; @@ -1215,6 +1239,7 @@ public final class ActivityThread { private static final class ServiceArgsData { IBinder token; int startId; + int flags; Intent args; public String toString() { return "ServiceArgsData{token=" + token + " startId=" + startId @@ -1270,10 +1295,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( @@ -1342,7 +1367,7 @@ public final class ActivityThread { synchronized (mRelaunchingActivities) { mRelaunchingActivities.add(r); } - + queueOrSendMessage(H.RELAUNCH_ACTIVITY, r, configChanges); } @@ -1417,10 +1442,11 @@ public final class ActivityThread { } public final void scheduleServiceArgs(IBinder token, int startId, - Intent args) { + int flags ,Intent args) { ServiceArgsData s = new ServiceArgsData(); s.token = token; s.startId = startId; + s.flags = flags; s.args = args; queueOrSendMessage(H.SERVICE_ARGS, s); @@ -1436,7 +1462,6 @@ public final class ActivityThread { Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, int debugMode, boolean isRestrictedBackupMode, Configuration config, Map<String, IBinder> services) { - Process.setArgV0(processName); if (services != null) { // Setup the service cache in the ServiceManager @@ -1461,6 +1486,10 @@ public final class ActivityThread { queueOrSendMessage(H.EXIT_APPLICATION, null); } + public final void scheduleSuicide() { + queueOrSendMessage(H.SUICIDE, null); + } + public void requestThumbnail(IBinder token) { queueOrSendMessage(H.REQUEST_THUMBNAIL, token); } @@ -1504,11 +1533,11 @@ public final class ActivityThread { // correctly ordered, since these are one-way calls and the binder driver // applies transaction ordering per object for such calls. public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, - int resultCode, String dataStr, Bundle extras, boolean ordered) - throws RemoteException { - receiver.performReceive(intent, resultCode, dataStr, extras, ordered); + int resultCode, String dataStr, Bundle extras, boolean ordered, + boolean sticky) throws RemoteException { + receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky); } - + public void scheduleLowMemory() { queueOrSendMessage(H.LOW_MEMORY, null); } @@ -1524,7 +1553,7 @@ public final class ActivityThread { } catch (RemoteException e) { } } - + public void profilerControl(boolean start, String path, ParcelFileDescriptor fd) { ProfilerControlData pcd = new ProfilerControlData(); pcd.path = path; @@ -1543,7 +1572,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; @@ -1579,7 +1612,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) { @@ -1587,79 +1620,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); @@ -1692,7 +1725,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"); @@ -1701,7 +1734,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) { @@ -1717,6 +1750,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; @@ -1746,7 +1783,9 @@ public final class ActivityThread { public static final int RELAUNCH_ACTIVITY = 126; public static final int PROFILER_CONTROL = 127; public static final int CREATE_BACKUP_AGENT = 128; - public static final int DESTROY_BACKUP_AGENT = 129; + public static final int DESTROY_BACKUP_AGENT = 129; + public static final int SUICIDE = 130; + public static final int REMOVE_PROVIDER = 131; String codeToString(int code) { if (localLOGV) { switch (code) { @@ -1780,6 +1819,8 @@ public final class ActivityThread { case PROFILER_CONTROL: return "PROFILER_CONTROL"; case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT"; case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT"; + case SUICIDE: return "SUICIDE"; + case REMOVE_PROVIDER: return "REMOVE_PROVIDER"; } } return "(unknown)"; @@ -1799,6 +1840,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); @@ -1841,6 +1883,7 @@ public final class ActivityThread { break; case RECEIVER: handleReceiver((ReceiverData)msg.obj); + maybeSnapshot(); break; case CREATE_SERVICE: handleCreateService((CreateServiceData)msg.obj); @@ -1856,6 +1899,7 @@ public final class ActivityThread { break; case STOP_SERVICE: handleStopService((IBinder)msg.obj); + maybeSnapshot(); break; case REQUEST_THUMBNAIL: handleRequestThumbnail((IBinder)msg.obj); @@ -1888,6 +1932,19 @@ public final class ActivityThread { case DESTROY_BACKUP_AGENT: handleDestroyBackupAgent((CreateBackupAgentData)msg.obj); break; + case SUICIDE: + Process.killProcess(Process.myPid()); + break; + case REMOVE_PROVIDER: + completeRemoveProvider((IContentProvider)msg.obj); + break; + } + } + + void maybeSnapshot() { + if (mBoundApplication != null) { + SamplingProfilerIntegration.writeSnapshot( + mBoundApplication.processName); } } } @@ -1906,7 +1963,8 @@ public final class ActivityThread { (a.activity != null ? a.activity.mFinished : false)); if (a.activity != null && !a.activity.mFinished) { try { - am.activityIdle(a.token); + am.activityIdle(a.token, a.createdConfig); + a.createdConfig = null; } catch (RemoteException ex) { } } @@ -1930,13 +1988,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; @@ -1987,7 +2045,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. @@ -2122,7 +2180,7 @@ public final class ActivityThread { return false; } } - + ActivityThread() { } @@ -2155,17 +2213,17 @@ public final class ActivityThread { public Application getApplication() { return mInitialApplication; } - + public String getProcessName() { return mBoundApplication.processName; } - + public ApplicationContext getSystemContext() { synchronized (this) { if (mSystemContext == null) { ApplicationContext context = ApplicationContext.createSystemContext(this); - PackageInfo info = new PackageInfo(this, "android", context); + PackageInfo info = new PackageInfo(this, "android", context, null); context.init(info, null, this); context.getResources().updateConfiguration( getConfiguration(), getDisplayMetricsLocked(false)); @@ -2177,6 +2235,13 @@ public final class ActivityThread { return mSystemContext; } + public void installSystemApplicationInfo(ApplicationInfo info) { + synchronized (this) { + ApplicationContext context = getSystemContext(); + context.init(new PackageInfo(this, "android", context, info), null, this); + } + } + void scheduleGcIdler() { if (!mGcIdlerScheduled) { mGcIdlerScheduled = true; @@ -2214,7 +2279,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) { @@ -2297,7 +2362,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( @@ -2328,8 +2393,8 @@ public final class ActivityThread { } try { - Application app = r.packageInfo.makeApplication(false); - + Application app = r.packageInfo.makeApplication(false, mInstrumentation); + if (localLOGV) Log.v(TAG, "Performing launch of " + r); if (localLOGV) Log.v( TAG, r + ": app=" + app @@ -2344,11 +2409,13 @@ public final class ActivityThread { appContext.setOuterContext(activity); CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); Configuration config = new Configuration(mConfiguration); + if (DEBUG_CONFIGURATION) Log.v(TAG, "Launching activity " + + r.activityInfo.name + " with config " + config); activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstance, r.lastNonConfigurationChildInstances, config); - + if (customIntent != null) { activity.mIntent = customIntent; } @@ -2417,6 +2484,7 @@ public final class ActivityThread { Activity a = performLaunchActivity(r, customIntent); if (a != null) { + r.createdConfig = new Configuration(a.getResources().getConfiguration()); handleResumeActivity(r.token, false, r.isForward); if (!r.activity.mFinished && r.startsNotResumed) { @@ -2486,7 +2554,7 @@ public final class ActivityThread { } } } - + private final void handleNewIntent(NewIntentData data) { performNewIntents(data.token, data.intents); } @@ -2523,8 +2591,8 @@ public final class ActivityThread { } try { - Application app = packageInfo.makeApplication(false); - + Application app = packageInfo.makeApplication(false, mInstrumentation); + if (localLOGV) Log.v( TAG, "Performing receive of " + data.intent + ": app=" + app @@ -2581,7 +2649,7 @@ public final class ActivityThread { + " already exists"); return; } - + BackupAgent agent = null; String classname = data.appInfo.backupAgentName; if (classname == null) { @@ -2635,7 +2703,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); @@ -2677,14 +2745,15 @@ public final class ActivityThread { ApplicationContext context = new ApplicationContext(); context.init(packageInfo, null, this); - Application app = packageInfo.makeApplication(false); + Application app = packageInfo.makeApplication(false, mInstrumentation); context.setOuterContext(service); service.attach(context, this, data.info.name, data.token, app, ActivityManagerNative.getDefault()); service.onCreate(); mServices.put(data.token, service); try { - ActivityManagerNative.getDefault().serviceDoneExecuting(data.token); + ActivityManagerNative.getDefault().serviceDoneExecuting( + data.token, 0, 0, 0); } catch (RemoteException e) { // nothing to do. } @@ -2710,7 +2779,7 @@ public final class ActivityThread { } else { s.onRebind(data.intent); ActivityManagerNative.getDefault().serviceDoneExecuting( - data.token); + data.token, 0, 0, 0); } } catch (RemoteException ex) { } @@ -2736,7 +2805,7 @@ public final class ActivityThread { data.token, data.intent, doRebind); } else { ActivityManagerNative.getDefault().serviceDoneExecuting( - data.token); + data.token, 0, 0, 0); } } catch (RemoteException ex) { } @@ -2773,9 +2842,10 @@ public final class ActivityThread { if (data.args != null) { data.args.setExtrasClassLoader(s.getClassLoader()); } - s.onStart(data.args, data.startId); + int res = s.onStartCommand(data.args, data.flags, data.startId); try { - ActivityManagerNative.getDefault().serviceDoneExecuting(data.token); + ActivityManagerNative.getDefault().serviceDoneExecuting( + data.token, 1, data.startId, res); } catch (RemoteException e) { // nothing to do. } @@ -2801,7 +2871,8 @@ public final class ActivityThread { ((ApplicationContext) context).scheduleFinalCleanup(who, "Service"); } try { - ActivityManagerNative.getDefault().serviceDoneExecuting(token); + ActivityManagerNative.getDefault().serviceDoneExecuting( + token, 0, 0, 0); } catch (RemoteException e) { // nothing to do. } @@ -2837,9 +2908,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) { @@ -2875,7 +2946,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. @@ -2904,9 +2975,11 @@ public final class ActivityThread { // The window is now visible if it has been added, we are not // simply finishing, and we are not starting another activity. - if (!r.activity.mFinished && r.activity.mDecor != null - && !r.hideForNow) { + if (!r.activity.mFinished && !a.mStartedActivity + && r.activity.mDecor != null && !r.hideForNow) { if (r.newConfig != null) { + if (DEBUG_CONFIGURATION) Log.v(TAG, "Resuming activity " + + r.activityInfo.name + " with newConfig " + r.newConfig); performConfigurationChanged(r.activity, r.newConfig); r.newConfig = null; } @@ -2919,9 +2992,11 @@ public final class ActivityThread { l.softInputMode = (l.softInputMode & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)) | forwardBit; - ViewManager wm = a.getWindowManager(); - View decor = r.window.getDecorView(); - wm.updateViewLayout(decor, l); + if (r.activity.mVisibleFromClient) { + ViewManager wm = a.getWindowManager(); + View decor = r.window.getDecorView(); + wm.updateViewLayout(decor, l); + } } r.activity.mVisibleFromServer = true; mNumVisibleActivities++; @@ -2994,7 +3069,7 @@ public final class ActivityThread { if (userLeaving) { performUserLeavingActivity(r); } - + r.activity.mConfigChangeFlags |= configChanges; Bundle state = performPauseActivity(token, finished, true); @@ -3146,6 +3221,8 @@ public final class ActivityThread { } } if (r.newConfig != null) { + if (DEBUG_CONFIGURATION) Log.v(TAG, "Updating activity vis " + + r.activityInfo.name + " with new config " + r.newConfig); performConfigurationChanged(r.activity, r.newConfig); r.newConfig = null; } @@ -3171,7 +3248,7 @@ public final class ActivityThread { + " win=" + r.window); updateVisibility(r, show); - + // Tell activity manager we have been stopped. try { ActivityManagerNative.getDefault().activityStopped( @@ -3287,7 +3364,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( @@ -3344,7 +3421,7 @@ public final class ActivityThread { + ": " + e.toString(), e); } } - + } try { r.activity.mCalled = false; @@ -3426,6 +3503,10 @@ public final class ActivityThread { unscheduleGcIdler(); Configuration changedConfig = null; + + if (DEBUG_CONFIGURATION) Log.v(TAG, "Relaunching activity " + + tmp.token + " with configChanges=0x" + + Integer.toHexString(configChanges)); // First: make sure we have the most recent configuration and most // recent version of the activity, or skip it if some previous call @@ -3443,38 +3524,42 @@ public final class ActivityThread { N--; } } - + if (tmp == null) { + if (DEBUG_CONFIGURATION) Log.v(TAG, "Abort, activity not relaunching!"); return; } - + if (mPendingConfiguration != null) { changedConfig = mPendingConfiguration; mPendingConfiguration = null; } } + + if (DEBUG_CONFIGURATION) Log.v(TAG, "Relaunching activity " + + tmp.token + ": changedConfig=" + changedConfig); // 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 (DEBUG_CONFIGURATION) 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; @@ -3498,7 +3583,7 @@ public final class ActivityThread { if (savedState != null) { r.state = savedState; } - + handleLaunchActivity(r, currentIntent); } @@ -3528,7 +3613,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()) { @@ -3546,6 +3631,8 @@ public final class ActivityThread { // the activity manager may, before then, decide the // activity needs to be destroyed to handle its new // configuration. + if (DEBUG_CONFIGURATION) Log.v(TAG, "Setting activity " + + ar.activityInfo.name + " newConfig=" + newConfig); ar.newConfig = newConfig; } } @@ -3569,10 +3656,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 @@ -3582,18 +3669,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. @@ -3602,10 +3689,12 @@ public final class ActivityThread { } } } - + + if (DEBUG_CONFIGURATION) Log.v(TAG, "Config callback " + cb + + ": shouldChangeConfig=" + shouldChangeConfig); if (shouldChangeConfig) { cb.onConfigurationChanged(config); - + if (activity != null) { if (!activity.mCalled) { throw new SuperNotCalledException( @@ -3619,16 +3708,19 @@ public final class ActivityThread { } final void handleConfigurationChanged(Configuration config) { - + synchronized (mRelaunchingActivities) { if (mPendingConfiguration != null) { config = mPendingConfiguration; mPendingConfiguration = null; } } - + ArrayList<ComponentCallbacks> callbacks = new ArrayList<ComponentCallbacks>(); + + if (DEBUG_CONFIGURATION) Log.v(TAG, "Handle configuration changed: " + + config); synchronized(mPackages) { if (mConfiguration == null) { @@ -3664,10 +3756,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); @@ -3679,6 +3771,9 @@ public final class ActivityThread { if (r == null || r.activity == null) { return; } + + if (DEBUG_CONFIGURATION) Log.v(TAG, "Handle activity config changed: " + + r.activityInfo.name); performConfigurationChanged(r.activity, mConfiguration); } @@ -3702,7 +3797,7 @@ public final class ActivityThread { Debug.stopMethodTracing(); } } - + final void handleLowMemory() { ArrayList<ComponentCallbacks> callbacks = new ArrayList<ComponentCallbacks>(); @@ -3710,7 +3805,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(); @@ -3721,7 +3816,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(); @@ -3737,6 +3832,7 @@ public final class ActivityThread { //Process.setUid(data.appInfo.uid); // send up app name; do this *before* waiting for debugger + Process.setArgV0(data.processName); android.ddm.DdmHandleAppName.setAppName(data.processName); /* @@ -3768,7 +3864,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); @@ -3859,7 +3955,7 @@ public final class ActivityThread { // If the app is being launched for full backup or restore, bring it up in // a restricted environment with the base application class. - Application app = data.info.makeApplication(data.restrictedBackupMode); + Application app = data.info.makeApplication(data.restrictedBackupMode, null); mInitialApplication = app; List<ProviderInfo> providers = data.providers; @@ -3992,22 +4088,51 @@ public final class ActivityThread { } else { prc.count--; if(prc.count == 0) { - mProviderRefCountMap.remove(jBinder); - //invoke removeProvider to dereference provider - removeProviderLocked(provider); + // Schedule the actual remove asynchronously, since we + // don't know the context this will be called in. + // TODO: it would be nice to post a delayed message, so + // if we come back and need the same provider quickly + // we will still have it available. + Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider); + mH.sendMessage(msg); } //end if } //end else } //end synchronized return true; } - public final void removeProviderLocked(IContentProvider provider) { + final void completeRemoveProvider(IContentProvider provider) { + IBinder jBinder = provider.asBinder(); + String name = null; + synchronized(mProviderMap) { + ProviderRefCount prc = mProviderRefCountMap.get(jBinder); + if(prc != null && prc.count == 0) { + mProviderRefCountMap.remove(jBinder); + //invoke removeProvider to dereference provider + name = removeProviderLocked(provider); + } + } + + if (name != null) { + try { + if(localLOGV) Log.v(TAG, "removeProvider::Invoking " + + "ActivityManagerNative.removeContentProvider(" + name); + ActivityManagerNative.getDefault().removeContentProvider( + getApplicationThread(), name); + } catch (RemoteException e) { + //do nothing content provider object is dead any way + } //end catch + } + } + + public final String removeProviderLocked(IContentProvider provider) { if (provider == null) { - return; + return null; } IBinder providerBinder = provider.asBinder(); - boolean amRemoveFlag = false; + String name = null; + // remove the provider from mProviderMap Iterator<ProviderRecord> iter = mProviderMap.values().iterator(); while (iter.hasNext()) { @@ -4017,7 +4142,7 @@ public final class ActivityThread { //find if its published by this process itself if(pr.mLocalProvider != null) { if(localLOGV) Log.i(TAG, "removeProvider::found local provider returning"); - return; + return name; } if(localLOGV) Log.v(TAG, "removeProvider::Not local provider Unlinking " + "death recipient"); @@ -4025,18 +4150,13 @@ public final class ActivityThread { myBinder.unlinkToDeath(pr, 0); iter.remove(); //invoke remove only once for the very first name seen - if(!amRemoveFlag) { - try { - if(localLOGV) Log.v(TAG, "removeProvider::Invoking " + - "ActivityManagerNative.removeContentProvider("+pr.mName); - ActivityManagerNative.getDefault().removeContentProvider(getApplicationThread(), pr.mName); - amRemoveFlag = true; - } catch (RemoteException e) { - //do nothing content provider object is dead any way - } //end catch + if(name == null) { + name = pr.mName; } } //end if myBinder } //end while iter + + return name; } final void removeDeadProvider(String name, IContentProvider provider) { @@ -4193,6 +4313,8 @@ public final class ActivityThread { } public static final void main(String[] args) { + SamplingProfilerIntegration.start(); + Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper(); @@ -4207,9 +4329,9 @@ public final class ActivityThread { } thread.detach(); - String name; - if (thread.mInitialApplication != null) name = thread.mInitialApplication.getPackageName(); - else name = "<unknown>"; + String name = (thread.mInitialApplication != null) + ? thread.mInitialApplication.getPackageName() + : "<unknown>"; Log.i(TAG, "Main thread of " + name + " is now exiting"); } } |