ActivityThread.java revision c9ad7c6dbb1d70b831cd79416cbe493ade50ed2c
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.app;
18
19import android.app.backup.BackupAgent;
20import android.content.BroadcastReceiver;
21import android.content.ComponentCallbacks;
22import android.content.ComponentName;
23import android.content.ContentProvider;
24import android.content.Context;
25import android.content.IContentProvider;
26import android.content.Intent;
27import android.content.IIntentReceiver;
28import android.content.pm.ActivityInfo;
29import android.content.pm.ApplicationInfo;
30import android.content.pm.IPackageManager;
31import android.content.pm.InstrumentationInfo;
32import android.content.pm.PackageManager;
33import android.content.pm.PackageManager.NameNotFoundException;
34import android.content.pm.ProviderInfo;
35import android.content.pm.ServiceInfo;
36import android.content.res.AssetManager;
37import android.content.res.CompatibilityInfo;
38import android.content.res.Configuration;
39import android.content.res.Resources;
40import android.database.sqlite.SQLiteDatabase;
41import android.database.sqlite.SQLiteDebug;
42import android.database.sqlite.SQLiteDebug.DbStats;
43import android.graphics.Bitmap;
44import android.graphics.Canvas;
45import android.os.Build;
46import android.os.Bundle;
47import android.os.Debug;
48import android.os.Handler;
49import android.os.IBinder;
50import android.os.Looper;
51import android.os.Message;
52import android.os.MessageQueue;
53import android.os.ParcelFileDescriptor;
54import android.os.Process;
55import android.os.RemoteException;
56import android.os.ServiceManager;
57import android.os.StrictMode;
58import android.os.SystemClock;
59import android.util.AndroidRuntimeException;
60import android.util.Config;
61import android.util.DisplayMetrics;
62import android.util.EventLog;
63import android.util.Log;
64import android.util.Slog;
65import android.view.Display;
66import android.view.View;
67import android.view.ViewDebug;
68import android.view.ViewManager;
69import android.view.ViewRoot;
70import android.view.Window;
71import android.view.WindowManager;
72import android.view.WindowManagerImpl;
73
74import com.android.internal.os.BinderInternal;
75import com.android.internal.os.RuntimeInit;
76import com.android.internal.os.SamplingProfilerIntegration;
77
78import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
79
80import java.io.File;
81import java.io.FileDescriptor;
82import java.io.FileOutputStream;
83import java.io.IOException;
84import java.io.PrintWriter;
85import java.lang.ref.WeakReference;
86import java.util.ArrayList;
87import java.util.HashMap;
88import java.util.Iterator;
89import java.util.List;
90import java.util.Locale;
91import java.util.Map;
92import java.util.TimeZone;
93import java.util.regex.Pattern;
94
95import dalvik.system.SamplingProfiler;
96
97final class SuperNotCalledException extends AndroidRuntimeException {
98    public SuperNotCalledException(String msg) {
99        super(msg);
100    }
101}
102
103final class RemoteServiceException extends AndroidRuntimeException {
104    public RemoteServiceException(String msg) {
105        super(msg);
106    }
107}
108
109/**
110 * This manages the execution of the main thread in an
111 * application process, scheduling and executing activities,
112 * broadcasts, and other operations on it as the activity
113 * manager requests.
114 *
115 * {@hide}
116 */
117public final class ActivityThread {
118    static final String TAG = "ActivityThread";
119    private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
120    private static final boolean DEBUG = false;
121    static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
122    static final boolean DEBUG_BROADCAST = false;
123    private static final boolean DEBUG_RESULTS = false;
124    private static final boolean DEBUG_BACKUP = false;
125    private static final boolean DEBUG_CONFIGURATION = false;
126    private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
127    private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";");
128    private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
129    private static final int LOG_ON_PAUSE_CALLED = 30021;
130    private static final int LOG_ON_RESUME_CALLED = 30022;
131
132    static ContextImpl mSystemContext = null;
133
134    static IPackageManager sPackageManager;
135
136    final ApplicationThread mAppThread = new ApplicationThread();
137    final Looper mLooper = Looper.myLooper();
138    final H mH = new H();
139    final HashMap<IBinder, ActivityClientRecord> mActivities
140            = new HashMap<IBinder, ActivityClientRecord>();
141    // List of new activities (via ActivityRecord.nextIdle) that should
142    // be reported when next we idle.
143    ActivityClientRecord mNewActivities = null;
144    // Number of activities that are currently visible on-screen.
145    int mNumVisibleActivities = 0;
146    final HashMap<IBinder, Service> mServices
147            = new HashMap<IBinder, Service>();
148    AppBindData mBoundApplication;
149    Configuration mConfiguration;
150    Configuration mResConfiguration;
151    Application mInitialApplication;
152    final ArrayList<Application> mAllApplications
153            = new ArrayList<Application>();
154    // set of instantiated backup agents, keyed by package name
155    final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>();
156    static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal();
157    Instrumentation mInstrumentation;
158    String mInstrumentationAppDir = null;
159    String mInstrumentationAppPackage = null;
160    String mInstrumentedAppDir = null;
161    boolean mSystemThread = false;
162    boolean mJitEnabled = false;
163
164    // These can be accessed by multiple threads; mPackages is the lock.
165    // XXX For now we keep around information about all packages we have
166    // seen, not removing entries from this map.
167    final HashMap<String, WeakReference<LoadedApk>> mPackages
168            = new HashMap<String, WeakReference<LoadedApk>>();
169    final HashMap<String, WeakReference<LoadedApk>> mResourcePackages
170            = new HashMap<String, WeakReference<LoadedApk>>();
171    Display mDisplay = null;
172    DisplayMetrics mDisplayMetrics = null;
173    final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
174            = new HashMap<ResourcesKey, WeakReference<Resources> >();
175    final ArrayList<ActivityClientRecord> mRelaunchingActivities
176            = new ArrayList<ActivityClientRecord>();
177    Configuration mPendingConfiguration = null;
178
179    // The lock of mProviderMap protects the following variables.
180    final HashMap<String, ProviderClientRecord> mProviderMap
181        = new HashMap<String, ProviderClientRecord>();
182    final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap
183        = new HashMap<IBinder, ProviderRefCount>();
184    final HashMap<IBinder, ProviderClientRecord> mLocalProviders
185        = new HashMap<IBinder, ProviderClientRecord>();
186
187    final GcIdler mGcIdler = new GcIdler();
188    boolean mGcIdlerScheduled = false;
189
190    static Handler sMainThreadHandler;  // set once in main()
191
192    private static final class ActivityClientRecord {
193        IBinder token;
194        int ident;
195        Intent intent;
196        Bundle state;
197        Activity activity;
198        Window window;
199        Activity parent;
200        String embeddedID;
201        Activity.NonConfigurationInstances lastNonConfigurationInstances;
202        boolean paused;
203        boolean stopped;
204        boolean hideForNow;
205        Configuration newConfig;
206        Configuration createdConfig;
207        ActivityClientRecord nextIdle;
208
209        ActivityInfo activityInfo;
210        LoadedApk packageInfo;
211
212        List<ResultInfo> pendingResults;
213        List<Intent> pendingIntents;
214
215        boolean startsNotResumed;
216        boolean isForward;
217
218        ActivityClientRecord() {
219            parent = null;
220            embeddedID = null;
221            paused = false;
222            stopped = false;
223            hideForNow = false;
224            nextIdle = null;
225        }
226
227        public String toString() {
228            ComponentName componentName = intent.getComponent();
229            return "ActivityRecord{"
230                + Integer.toHexString(System.identityHashCode(this))
231                + " token=" + token + " " + (componentName == null
232                        ? "no component name" : componentName.toShortString())
233                + "}";
234        }
235    }
236
237    private final class ProviderClientRecord implements IBinder.DeathRecipient {
238        final String mName;
239        final IContentProvider mProvider;
240        final ContentProvider mLocalProvider;
241
242        ProviderClientRecord(String name, IContentProvider provider,
243                ContentProvider localProvider) {
244            mName = name;
245            mProvider = provider;
246            mLocalProvider = localProvider;
247        }
248
249        public void binderDied() {
250            removeDeadProvider(mName, mProvider);
251        }
252    }
253
254    private static final class NewIntentData {
255        List<Intent> intents;
256        IBinder token;
257        public String toString() {
258            return "NewIntentData{intents=" + intents + " token=" + token + "}";
259        }
260    }
261
262    private static final class ReceiverData {
263        Intent intent;
264        ActivityInfo info;
265        int resultCode;
266        String resultData;
267        Bundle resultExtras;
268        boolean sync;
269        boolean resultAbort;
270        public String toString() {
271            return "ReceiverData{intent=" + intent + " packageName=" +
272            info.packageName + " resultCode=" + resultCode
273            + " resultData=" + resultData + " resultExtras=" + resultExtras + "}";
274        }
275    }
276
277    private static final class CreateBackupAgentData {
278        ApplicationInfo appInfo;
279        int backupMode;
280        public String toString() {
281            return "CreateBackupAgentData{appInfo=" + appInfo
282                    + " backupAgent=" + appInfo.backupAgentName
283                    + " mode=" + backupMode + "}";
284        }
285    }
286
287    private static final class CreateServiceData {
288        IBinder token;
289        ServiceInfo info;
290        Intent intent;
291        public String toString() {
292            return "CreateServiceData{token=" + token + " className="
293            + info.name + " packageName=" + info.packageName
294            + " intent=" + intent + "}";
295        }
296    }
297
298    private static final class BindServiceData {
299        IBinder token;
300        Intent intent;
301        boolean rebind;
302        public String toString() {
303            return "BindServiceData{token=" + token + " intent=" + intent + "}";
304        }
305    }
306
307    private static final class ServiceArgsData {
308        IBinder token;
309        int startId;
310        int flags;
311        Intent args;
312        public String toString() {
313            return "ServiceArgsData{token=" + token + " startId=" + startId
314            + " args=" + args + "}";
315        }
316    }
317
318    private static final class AppBindData {
319        LoadedApk info;
320        String processName;
321        ApplicationInfo appInfo;
322        List<ProviderInfo> providers;
323        ComponentName instrumentationName;
324        String profileFile;
325        Bundle instrumentationArgs;
326        IInstrumentationWatcher instrumentationWatcher;
327        int debugMode;
328        boolean restrictedBackupMode;
329        Configuration config;
330        boolean handlingProfiling;
331        public String toString() {
332            return "AppBindData{appInfo=" + appInfo + "}";
333        }
334    }
335
336    private static final class DumpServiceInfo {
337        FileDescriptor fd;
338        IBinder service;
339        String[] args;
340        boolean dumped;
341    }
342
343    private static final class ResultData {
344        IBinder token;
345        List<ResultInfo> results;
346        public String toString() {
347            return "ResultData{token=" + token + " results" + results + "}";
348        }
349    }
350
351    private static final class ContextCleanupInfo {
352        ContextImpl context;
353        String what;
354        String who;
355    }
356
357    private static final class ProfilerControlData {
358        String path;
359        ParcelFileDescriptor fd;
360    }
361
362    private static final class DumpHeapData {
363        String path;
364        ParcelFileDescriptor fd;
365    }
366
367    private final class ApplicationThread extends ApplicationThreadNative {
368        private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
369        private static final String ONE_COUNT_COLUMN = "%17s %8d";
370        private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d";
371        private static final String DB_INFO_FORMAT = "  %4d %6d %8d %14s  %s";
372
373        // Formatting for checkin service - update version if row format changes
374        private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1;
375
376        public final void schedulePauseActivity(IBinder token, boolean finished,
377                boolean userLeaving, int configChanges) {
378            queueOrSendMessage(
379                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
380                    token,
381                    (userLeaving ? 1 : 0),
382                    configChanges);
383        }
384
385        public final void scheduleStopActivity(IBinder token, boolean showWindow,
386                int configChanges) {
387           queueOrSendMessage(
388                showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
389                token, 0, configChanges);
390        }
391
392        public final void scheduleWindowVisibility(IBinder token, boolean showWindow) {
393            queueOrSendMessage(
394                showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW,
395                token);
396        }
397
398        public final void scheduleResumeActivity(IBinder token, boolean isForward) {
399            queueOrSendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
400        }
401
402        public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
403            ResultData res = new ResultData();
404            res.token = token;
405            res.results = results;
406            queueOrSendMessage(H.SEND_RESULT, res);
407        }
408
409        // we use token to identify this activity without having to send the
410        // activity itself back to the activity manager. (matters more with ipc)
411        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
412                ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
413                List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) {
414            ActivityClientRecord r = new ActivityClientRecord();
415
416            r.token = token;
417            r.ident = ident;
418            r.intent = intent;
419            r.activityInfo = info;
420            r.state = state;
421
422            r.pendingResults = pendingResults;
423            r.pendingIntents = pendingNewIntents;
424
425            r.startsNotResumed = notResumed;
426            r.isForward = isForward;
427
428            queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
429        }
430
431        public final void scheduleRelaunchActivity(IBinder token,
432                List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
433                int configChanges, boolean notResumed, Configuration config) {
434            ActivityClientRecord r = new ActivityClientRecord();
435
436            r.token = token;
437            r.pendingResults = pendingResults;
438            r.pendingIntents = pendingNewIntents;
439            r.startsNotResumed = notResumed;
440            r.createdConfig = config;
441
442            synchronized (mPackages) {
443                mRelaunchingActivities.add(r);
444            }
445
446            queueOrSendMessage(H.RELAUNCH_ACTIVITY, r, configChanges);
447        }
448
449        public final void scheduleNewIntent(List<Intent> intents, IBinder token) {
450            NewIntentData data = new NewIntentData();
451            data.intents = intents;
452            data.token = token;
453
454            queueOrSendMessage(H.NEW_INTENT, data);
455        }
456
457        public final void scheduleDestroyActivity(IBinder token, boolean finishing,
458                int configChanges) {
459            queueOrSendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
460                    configChanges);
461        }
462
463        public final void scheduleReceiver(Intent intent, ActivityInfo info,
464                int resultCode, String data, Bundle extras, boolean sync) {
465            ReceiverData r = new ReceiverData();
466
467            r.intent = intent;
468            r.info = info;
469            r.resultCode = resultCode;
470            r.resultData = data;
471            r.resultExtras = extras;
472            r.sync = sync;
473
474            queueOrSendMessage(H.RECEIVER, r);
475        }
476
477        public final void scheduleCreateBackupAgent(ApplicationInfo app, int backupMode) {
478            CreateBackupAgentData d = new CreateBackupAgentData();
479            d.appInfo = app;
480            d.backupMode = backupMode;
481
482            queueOrSendMessage(H.CREATE_BACKUP_AGENT, d);
483        }
484
485        public final void scheduleDestroyBackupAgent(ApplicationInfo app) {
486            CreateBackupAgentData d = new CreateBackupAgentData();
487            d.appInfo = app;
488
489            queueOrSendMessage(H.DESTROY_BACKUP_AGENT, d);
490        }
491
492        public final void scheduleCreateService(IBinder token,
493                ServiceInfo info) {
494            CreateServiceData s = new CreateServiceData();
495            s.token = token;
496            s.info = info;
497
498            queueOrSendMessage(H.CREATE_SERVICE, s);
499        }
500
501        public final void scheduleBindService(IBinder token, Intent intent,
502                boolean rebind) {
503            BindServiceData s = new BindServiceData();
504            s.token = token;
505            s.intent = intent;
506            s.rebind = rebind;
507
508            queueOrSendMessage(H.BIND_SERVICE, s);
509        }
510
511        public final void scheduleUnbindService(IBinder token, Intent intent) {
512            BindServiceData s = new BindServiceData();
513            s.token = token;
514            s.intent = intent;
515
516            queueOrSendMessage(H.UNBIND_SERVICE, s);
517        }
518
519        public final void scheduleServiceArgs(IBinder token, int startId,
520            int flags ,Intent args) {
521            ServiceArgsData s = new ServiceArgsData();
522            s.token = token;
523            s.startId = startId;
524            s.flags = flags;
525            s.args = args;
526
527            queueOrSendMessage(H.SERVICE_ARGS, s);
528        }
529
530        public final void scheduleStopService(IBinder token) {
531            queueOrSendMessage(H.STOP_SERVICE, token);
532        }
533
534        public final void bindApplication(String processName,
535                ApplicationInfo appInfo, List<ProviderInfo> providers,
536                ComponentName instrumentationName, String profileFile,
537                Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
538                int debugMode, boolean isRestrictedBackupMode, Configuration config,
539                Map<String, IBinder> services) {
540
541            if (services != null) {
542                // Setup the service cache in the ServiceManager
543                ServiceManager.initServiceCache(services);
544            }
545
546            AppBindData data = new AppBindData();
547            data.processName = processName;
548            data.appInfo = appInfo;
549            data.providers = providers;
550            data.instrumentationName = instrumentationName;
551            data.profileFile = profileFile;
552            data.instrumentationArgs = instrumentationArgs;
553            data.instrumentationWatcher = instrumentationWatcher;
554            data.debugMode = debugMode;
555            data.restrictedBackupMode = isRestrictedBackupMode;
556            data.config = config;
557            queueOrSendMessage(H.BIND_APPLICATION, data);
558        }
559
560        public final void scheduleExit() {
561            queueOrSendMessage(H.EXIT_APPLICATION, null);
562        }
563
564        public final void scheduleSuicide() {
565            queueOrSendMessage(H.SUICIDE, null);
566        }
567
568        public void requestThumbnail(IBinder token) {
569            queueOrSendMessage(H.REQUEST_THUMBNAIL, token);
570        }
571
572        public void scheduleConfigurationChanged(Configuration config) {
573            synchronized (mPackages) {
574                if (mPendingConfiguration == null ||
575                        mPendingConfiguration.isOtherSeqNewer(config)) {
576                    mPendingConfiguration = config;
577                }
578            }
579            queueOrSendMessage(H.CONFIGURATION_CHANGED, config);
580        }
581
582        public void updateTimeZone() {
583            TimeZone.setDefault(null);
584        }
585
586        public void processInBackground() {
587            mH.removeMessages(H.GC_WHEN_IDLE);
588            mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
589        }
590
591        public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) {
592            DumpServiceInfo data = new DumpServiceInfo();
593            data.fd = fd;
594            data.service = servicetoken;
595            data.args = args;
596            data.dumped = false;
597            queueOrSendMessage(H.DUMP_SERVICE, data);
598            synchronized (data) {
599                while (!data.dumped) {
600                    try {
601                        data.wait();
602                    } catch (InterruptedException e) {
603                        // no need to do anything here, we will keep waiting until
604                        // dumped is set
605                    }
606                }
607            }
608        }
609
610        // This function exists to make sure all receiver dispatching is
611        // correctly ordered, since these are one-way calls and the binder driver
612        // applies transaction ordering per object for such calls.
613        public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
614                int resultCode, String dataStr, Bundle extras, boolean ordered,
615                boolean sticky) throws RemoteException {
616            receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);
617        }
618
619        public void scheduleLowMemory() {
620            queueOrSendMessage(H.LOW_MEMORY, null);
621        }
622
623        public void scheduleActivityConfigurationChanged(IBinder token) {
624            queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);
625        }
626
627        public void profilerControl(boolean start, String path, ParcelFileDescriptor fd) {
628            ProfilerControlData pcd = new ProfilerControlData();
629            pcd.path = path;
630            pcd.fd = fd;
631            queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0);
632        }
633
634        public void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) {
635            DumpHeapData dhd = new DumpHeapData();
636            dhd.path = path;
637            dhd.fd = fd;
638            queueOrSendMessage(H.DUMP_HEAP, dhd, managed ? 1 : 0);
639        }
640
641        public void setSchedulingGroup(int group) {
642            // Note: do this immediately, since going into the foreground
643            // should happen regardless of what pending work we have to do
644            // and the activity manager will wait for us to report back that
645            // we are done before sending us to the background.
646            try {
647                Process.setProcessGroup(Process.myPid(), group);
648            } catch (Exception e) {
649                Slog.w(TAG, "Failed setting process group to " + group, e);
650            }
651        }
652
653        public void getMemoryInfo(Debug.MemoryInfo outInfo) {
654            Debug.getMemoryInfo(outInfo);
655        }
656
657        public void dispatchPackageBroadcast(int cmd, String[] packages) {
658            queueOrSendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
659        }
660
661        public void scheduleCrash(String msg) {
662            queueOrSendMessage(H.SCHEDULE_CRASH, msg);
663        }
664
665        @Override
666        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
667            long nativeMax = Debug.getNativeHeapSize() / 1024;
668            long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
669            long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
670
671            Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
672            Debug.getMemoryInfo(memInfo);
673
674            final int nativeShared = memInfo.nativeSharedDirty;
675            final int dalvikShared = memInfo.dalvikSharedDirty;
676            final int otherShared = memInfo.otherSharedDirty;
677
678            final int nativePrivate = memInfo.nativePrivateDirty;
679            final int dalvikPrivate = memInfo.dalvikPrivateDirty;
680            final int otherPrivate = memInfo.otherPrivateDirty;
681
682            Runtime runtime = Runtime.getRuntime();
683
684            long dalvikMax = runtime.totalMemory() / 1024;
685            long dalvikFree = runtime.freeMemory() / 1024;
686            long dalvikAllocated = dalvikMax - dalvikFree;
687            long viewInstanceCount = ViewDebug.getViewInstanceCount();
688            long viewRootInstanceCount = ViewDebug.getViewRootInstanceCount();
689            long appContextInstanceCount = ContextImpl.getInstanceCount();
690            long activityInstanceCount = Activity.getInstanceCount();
691            int globalAssetCount = AssetManager.getGlobalAssetCount();
692            int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
693            int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
694            int binderProxyObjectCount = Debug.getBinderProxyObjectCount();
695            int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
696            int openSslSocketCount = OpenSSLSocketImpl.getInstanceCount();
697            long sqliteAllocated = SQLiteDebug.getHeapAllocatedSize() / 1024;
698            SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo();
699
700            // Check to see if we were called by checkin server. If so, print terse format.
701            boolean doCheckinFormat = false;
702            if (args != null) {
703                for (String arg : args) {
704                    if ("-c".equals(arg)) doCheckinFormat = true;
705                }
706            }
707
708            // For checkin, we print one long comma-separated list of values
709            if (doCheckinFormat) {
710                // NOTE: if you change anything significant below, also consider changing
711                // ACTIVITY_THREAD_CHECKIN_VERSION.
712                String processName = (mBoundApplication != null)
713                        ? mBoundApplication.processName : "unknown";
714
715                // Header
716                pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(',');
717                pw.print(Process.myPid()); pw.print(',');
718                pw.print(processName); pw.print(',');
719
720                // Heap info - max
721                pw.print(nativeMax); pw.print(',');
722                pw.print(dalvikMax); pw.print(',');
723                pw.print("N/A,");
724                pw.print(nativeMax + dalvikMax); pw.print(',');
725
726                // Heap info - allocated
727                pw.print(nativeAllocated); pw.print(',');
728                pw.print(dalvikAllocated); pw.print(',');
729                pw.print("N/A,");
730                pw.print(nativeAllocated + dalvikAllocated); pw.print(',');
731
732                // Heap info - free
733                pw.print(nativeFree); pw.print(',');
734                pw.print(dalvikFree); pw.print(',');
735                pw.print("N/A,");
736                pw.print(nativeFree + dalvikFree); pw.print(',');
737
738                // Heap info - proportional set size
739                pw.print(memInfo.nativePss); pw.print(',');
740                pw.print(memInfo.dalvikPss); pw.print(',');
741                pw.print(memInfo.otherPss); pw.print(',');
742                pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(',');
743
744                // Heap info - shared
745                pw.print(nativeShared); pw.print(',');
746                pw.print(dalvikShared); pw.print(',');
747                pw.print(otherShared); pw.print(',');
748                pw.print(nativeShared + dalvikShared + otherShared); pw.print(',');
749
750                // Heap info - private
751                pw.print(nativePrivate); pw.print(',');
752                pw.print(dalvikPrivate); pw.print(',');
753                pw.print(otherPrivate); pw.print(',');
754                pw.print(nativePrivate + dalvikPrivate + otherPrivate); pw.print(',');
755
756                // Object counts
757                pw.print(viewInstanceCount); pw.print(',');
758                pw.print(viewRootInstanceCount); pw.print(',');
759                pw.print(appContextInstanceCount); pw.print(',');
760                pw.print(activityInstanceCount); pw.print(',');
761
762                pw.print(globalAssetCount); pw.print(',');
763                pw.print(globalAssetManagerCount); pw.print(',');
764                pw.print(binderLocalObjectCount); pw.print(',');
765                pw.print(binderProxyObjectCount); pw.print(',');
766
767                pw.print(binderDeathObjectCount); pw.print(',');
768                pw.print(openSslSocketCount); pw.print(',');
769
770                // SQL
771                pw.print(sqliteAllocated); pw.print(',');
772                pw.print(stats.memoryUsed / 1024); pw.print(',');
773                pw.print(stats.pageCacheOverflo / 1024); pw.print(',');
774                pw.print(stats.largestMemAlloc / 1024); pw.print(',');
775                for (int i = 0; i < stats.dbStats.size(); i++) {
776                    DbStats dbStats = stats.dbStats.get(i);
777                    printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize,
778                            dbStats.lookaside, dbStats.cache, dbStats.dbName);
779                    pw.print(',');
780                }
781
782                return;
783            }
784
785            // otherwise, show human-readable format
786            printRow(pw, HEAP_COLUMN, "", "native", "dalvik", "other", "total");
787            printRow(pw, HEAP_COLUMN, "size:", nativeMax, dalvikMax, "N/A", nativeMax + dalvikMax);
788            printRow(pw, HEAP_COLUMN, "allocated:", nativeAllocated, dalvikAllocated, "N/A",
789                    nativeAllocated + dalvikAllocated);
790            printRow(pw, HEAP_COLUMN, "free:", nativeFree, dalvikFree, "N/A",
791                    nativeFree + dalvikFree);
792
793            printRow(pw, HEAP_COLUMN, "(Pss):", memInfo.nativePss, memInfo.dalvikPss,
794                    memInfo.otherPss, memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss);
795
796            printRow(pw, HEAP_COLUMN, "(shared dirty):", nativeShared, dalvikShared, otherShared,
797                    nativeShared + dalvikShared + otherShared);
798            printRow(pw, HEAP_COLUMN, "(priv dirty):", nativePrivate, dalvikPrivate, otherPrivate,
799                    nativePrivate + dalvikPrivate + otherPrivate);
800
801            pw.println(" ");
802            pw.println(" Objects");
803            printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRoots:",
804                    viewRootInstanceCount);
805
806            printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount,
807                    "Activities:", activityInstanceCount);
808
809            printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount,
810                    "AssetManagers:", globalAssetManagerCount);
811
812            printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount,
813                    "Proxy Binders:", binderProxyObjectCount);
814            printRow(pw, ONE_COUNT_COLUMN, "Death Recipients:", binderDeathObjectCount);
815
816            printRow(pw, ONE_COUNT_COLUMN, "OpenSSL Sockets:", openSslSocketCount);
817
818            // SQLite mem info
819            pw.println(" ");
820            pw.println(" SQL");
821            printRow(pw, TWO_COUNT_COLUMNS, "heap:", sqliteAllocated, "memoryUsed:",
822                    stats.memoryUsed / 1024);
823            printRow(pw, TWO_COUNT_COLUMNS, "pageCacheOverflo:", stats.pageCacheOverflo / 1024,
824                    "largestMemAlloc:", stats.largestMemAlloc / 1024);
825            pw.println(" ");
826            int N = stats.dbStats.size();
827            if (N > 0) {
828                pw.println(" DATABASES");
829                printRow(pw, "  %4s %6s %8s %14s  %s", "pgsz", "dbsz", "lkaside", "cache",
830                    "Dbname");
831                for (int i = 0; i < N; i++) {
832                    DbStats dbStats = stats.dbStats.get(i);
833                    printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize,
834                            dbStats.lookaside, dbStats.cache, dbStats.dbName);
835                }
836            }
837
838            // Asset details.
839            String assetAlloc = AssetManager.getAssetAllocations();
840            if (assetAlloc != null) {
841                pw.println(" ");
842                pw.println(" Asset Allocations");
843                pw.print(assetAlloc);
844            }
845        }
846
847        private void printRow(PrintWriter pw, String format, Object...objs) {
848            pw.println(String.format(format, objs));
849        }
850    }
851
852    private final class H extends Handler {
853        public static final int LAUNCH_ACTIVITY         = 100;
854        public static final int PAUSE_ACTIVITY          = 101;
855        public static final int PAUSE_ACTIVITY_FINISHING= 102;
856        public static final int STOP_ACTIVITY_SHOW      = 103;
857        public static final int STOP_ACTIVITY_HIDE      = 104;
858        public static final int SHOW_WINDOW             = 105;
859        public static final int HIDE_WINDOW             = 106;
860        public static final int RESUME_ACTIVITY         = 107;
861        public static final int SEND_RESULT             = 108;
862        public static final int DESTROY_ACTIVITY         = 109;
863        public static final int BIND_APPLICATION        = 110;
864        public static final int EXIT_APPLICATION        = 111;
865        public static final int NEW_INTENT              = 112;
866        public static final int RECEIVER                = 113;
867        public static final int CREATE_SERVICE          = 114;
868        public static final int SERVICE_ARGS            = 115;
869        public static final int STOP_SERVICE            = 116;
870        public static final int REQUEST_THUMBNAIL       = 117;
871        public static final int CONFIGURATION_CHANGED   = 118;
872        public static final int CLEAN_UP_CONTEXT        = 119;
873        public static final int GC_WHEN_IDLE            = 120;
874        public static final int BIND_SERVICE            = 121;
875        public static final int UNBIND_SERVICE          = 122;
876        public static final int DUMP_SERVICE            = 123;
877        public static final int LOW_MEMORY              = 124;
878        public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
879        public static final int RELAUNCH_ACTIVITY       = 126;
880        public static final int PROFILER_CONTROL        = 127;
881        public static final int CREATE_BACKUP_AGENT     = 128;
882        public static final int DESTROY_BACKUP_AGENT    = 129;
883        public static final int SUICIDE                 = 130;
884        public static final int REMOVE_PROVIDER         = 131;
885        public static final int ENABLE_JIT              = 132;
886        public static final int DISPATCH_PACKAGE_BROADCAST = 133;
887        public static final int SCHEDULE_CRASH          = 134;
888        public static final int DUMP_HEAP               = 135;
889        String codeToString(int code) {
890            if (localLOGV) {
891                switch (code) {
892                    case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
893                    case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
894                    case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";
895                    case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";
896                    case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";
897                    case SHOW_WINDOW: return "SHOW_WINDOW";
898                    case HIDE_WINDOW: return "HIDE_WINDOW";
899                    case RESUME_ACTIVITY: return "RESUME_ACTIVITY";
900                    case SEND_RESULT: return "SEND_RESULT";
901                    case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";
902                    case BIND_APPLICATION: return "BIND_APPLICATION";
903                    case EXIT_APPLICATION: return "EXIT_APPLICATION";
904                    case NEW_INTENT: return "NEW_INTENT";
905                    case RECEIVER: return "RECEIVER";
906                    case CREATE_SERVICE: return "CREATE_SERVICE";
907                    case SERVICE_ARGS: return "SERVICE_ARGS";
908                    case STOP_SERVICE: return "STOP_SERVICE";
909                    case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL";
910                    case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
911                    case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
912                    case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
913                    case BIND_SERVICE: return "BIND_SERVICE";
914                    case UNBIND_SERVICE: return "UNBIND_SERVICE";
915                    case DUMP_SERVICE: return "DUMP_SERVICE";
916                    case LOW_MEMORY: return "LOW_MEMORY";
917                    case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";
918                    case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
919                    case PROFILER_CONTROL: return "PROFILER_CONTROL";
920                    case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
921                    case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
922                    case SUICIDE: return "SUICIDE";
923                    case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
924                    case ENABLE_JIT: return "ENABLE_JIT";
925                    case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
926                    case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
927                    case DUMP_HEAP: return "DUMP_HEAP";
928                }
929            }
930            return "(unknown)";
931        }
932        public void handleMessage(Message msg) {
933            switch (msg.what) {
934                case LAUNCH_ACTIVITY: {
935                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
936
937                    r.packageInfo = getPackageInfoNoCheck(
938                            r.activityInfo.applicationInfo);
939                    handleLaunchActivity(r, null);
940                } break;
941                case RELAUNCH_ACTIVITY: {
942                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
943                    handleRelaunchActivity(r, msg.arg1);
944                } break;
945                case PAUSE_ACTIVITY:
946                    handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
947                    maybeSnapshot();
948                    break;
949                case PAUSE_ACTIVITY_FINISHING:
950                    handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);
951                    break;
952                case STOP_ACTIVITY_SHOW:
953                    handleStopActivity((IBinder)msg.obj, true, msg.arg2);
954                    break;
955                case STOP_ACTIVITY_HIDE:
956                    handleStopActivity((IBinder)msg.obj, false, msg.arg2);
957                    break;
958                case SHOW_WINDOW:
959                    handleWindowVisibility((IBinder)msg.obj, true);
960                    break;
961                case HIDE_WINDOW:
962                    handleWindowVisibility((IBinder)msg.obj, false);
963                    break;
964                case RESUME_ACTIVITY:
965                    handleResumeActivity((IBinder)msg.obj, true,
966                            msg.arg1 != 0);
967                    break;
968                case SEND_RESULT:
969                    handleSendResult((ResultData)msg.obj);
970                    break;
971                case DESTROY_ACTIVITY:
972                    handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
973                            msg.arg2, false);
974                    break;
975                case BIND_APPLICATION:
976                    AppBindData data = (AppBindData)msg.obj;
977                    handleBindApplication(data);
978                    break;
979                case EXIT_APPLICATION:
980                    if (mInitialApplication != null) {
981                        mInitialApplication.onTerminate();
982                    }
983                    Looper.myLooper().quit();
984                    break;
985                case NEW_INTENT:
986                    handleNewIntent((NewIntentData)msg.obj);
987                    break;
988                case RECEIVER:
989                    handleReceiver((ReceiverData)msg.obj);
990                    maybeSnapshot();
991                    break;
992                case CREATE_SERVICE:
993                    handleCreateService((CreateServiceData)msg.obj);
994                    break;
995                case BIND_SERVICE:
996                    handleBindService((BindServiceData)msg.obj);
997                    break;
998                case UNBIND_SERVICE:
999                    handleUnbindService((BindServiceData)msg.obj);
1000                    break;
1001                case SERVICE_ARGS:
1002                    handleServiceArgs((ServiceArgsData)msg.obj);
1003                    break;
1004                case STOP_SERVICE:
1005                    handleStopService((IBinder)msg.obj);
1006                    maybeSnapshot();
1007                    break;
1008                case REQUEST_THUMBNAIL:
1009                    handleRequestThumbnail((IBinder)msg.obj);
1010                    break;
1011                case CONFIGURATION_CHANGED:
1012                    handleConfigurationChanged((Configuration)msg.obj);
1013                    break;
1014                case CLEAN_UP_CONTEXT:
1015                    ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
1016                    cci.context.performFinalCleanup(cci.who, cci.what);
1017                    break;
1018                case GC_WHEN_IDLE:
1019                    scheduleGcIdler();
1020                    break;
1021                case DUMP_SERVICE:
1022                    handleDumpService((DumpServiceInfo)msg.obj);
1023                    break;
1024                case LOW_MEMORY:
1025                    handleLowMemory();
1026                    break;
1027                case ACTIVITY_CONFIGURATION_CHANGED:
1028                    handleActivityConfigurationChanged((IBinder)msg.obj);
1029                    break;
1030                case PROFILER_CONTROL:
1031                    handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj);
1032                    break;
1033                case CREATE_BACKUP_AGENT:
1034                    handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
1035                    break;
1036                case DESTROY_BACKUP_AGENT:
1037                    handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
1038                    break;
1039                case SUICIDE:
1040                    Process.killProcess(Process.myPid());
1041                    break;
1042                case REMOVE_PROVIDER:
1043                    completeRemoveProvider((IContentProvider)msg.obj);
1044                    break;
1045                case ENABLE_JIT:
1046                    ensureJitEnabled();
1047                    break;
1048                case DISPATCH_PACKAGE_BROADCAST:
1049                    handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
1050                    break;
1051                case SCHEDULE_CRASH:
1052                    throw new RemoteServiceException((String)msg.obj);
1053                case DUMP_HEAP:
1054                    handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj);
1055                    break;
1056            }
1057        }
1058
1059        void maybeSnapshot() {
1060            if (mBoundApplication != null) {
1061                // convert the *private* ActivityThread.PackageInfo to *public* known
1062                // android.content.pm.PackageInfo
1063                String packageName = mBoundApplication.info.mPackageName;
1064                android.content.pm.PackageInfo packageInfo = null;
1065                try {
1066                    Context context = getSystemContext();
1067                    if(context == null) {
1068                        Log.e(TAG, "cannot get a valid context");
1069                        return;
1070                    }
1071                    PackageManager pm = context.getPackageManager();
1072                    if(pm == null) {
1073                        Log.e(TAG, "cannot get a valid PackageManager");
1074                        return;
1075                    }
1076                    packageInfo = pm.getPackageInfo(
1077                            packageName, PackageManager.GET_ACTIVITIES);
1078                } catch (NameNotFoundException e) {
1079                    Log.e(TAG, "cannot get package info for " + packageName, e);
1080                }
1081                SamplingProfilerIntegration.writeSnapshot(mBoundApplication.processName, packageInfo);
1082            }
1083        }
1084    }
1085
1086    private final class Idler implements MessageQueue.IdleHandler {
1087        public final boolean queueIdle() {
1088            ActivityClientRecord a = mNewActivities;
1089            if (a != null) {
1090                mNewActivities = null;
1091                IActivityManager am = ActivityManagerNative.getDefault();
1092                ActivityClientRecord prev;
1093                do {
1094                    if (localLOGV) Slog.v(
1095                        TAG, "Reporting idle of " + a +
1096                        " finished=" +
1097                        (a.activity != null ? a.activity.mFinished : false));
1098                    if (a.activity != null && !a.activity.mFinished) {
1099                        try {
1100                            am.activityIdle(a.token, a.createdConfig);
1101                            a.createdConfig = null;
1102                        } catch (RemoteException ex) {
1103                        }
1104                    }
1105                    prev = a;
1106                    a = a.nextIdle;
1107                    prev.nextIdle = null;
1108                } while (a != null);
1109            }
1110            ensureJitEnabled();
1111            return false;
1112        }
1113    }
1114
1115    final class GcIdler implements MessageQueue.IdleHandler {
1116        public final boolean queueIdle() {
1117            doGcIfNeeded();
1118            return false;
1119        }
1120    }
1121
1122    private final static class ResourcesKey {
1123        final private String mResDir;
1124        final private float mScale;
1125        final private int mHash;
1126
1127        ResourcesKey(String resDir, float scale) {
1128            mResDir = resDir;
1129            mScale = scale;
1130            mHash = mResDir.hashCode() << 2 + (int) (mScale * 2);
1131        }
1132
1133        @Override
1134        public int hashCode() {
1135            return mHash;
1136        }
1137
1138        @Override
1139        public boolean equals(Object obj) {
1140            if (!(obj instanceof ResourcesKey)) {
1141                return false;
1142            }
1143            ResourcesKey peer = (ResourcesKey) obj;
1144            return mResDir.equals(peer.mResDir) && mScale == peer.mScale;
1145        }
1146    }
1147
1148    public static final ActivityThread currentActivityThread() {
1149        return sThreadLocal.get();
1150    }
1151
1152    public static final String currentPackageName() {
1153        ActivityThread am = currentActivityThread();
1154        return (am != null && am.mBoundApplication != null)
1155            ? am.mBoundApplication.processName : null;
1156    }
1157
1158    public static final Application currentApplication() {
1159        ActivityThread am = currentActivityThread();
1160        return am != null ? am.mInitialApplication : null;
1161    }
1162
1163    public static IPackageManager getPackageManager() {
1164        if (sPackageManager != null) {
1165            //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
1166            return sPackageManager;
1167        }
1168        IBinder b = ServiceManager.getService("package");
1169        //Slog.v("PackageManager", "default service binder = " + b);
1170        sPackageManager = IPackageManager.Stub.asInterface(b);
1171        //Slog.v("PackageManager", "default service = " + sPackageManager);
1172        return sPackageManager;
1173    }
1174
1175    DisplayMetrics getDisplayMetricsLocked(boolean forceUpdate) {
1176        if (mDisplayMetrics != null && !forceUpdate) {
1177            return mDisplayMetrics;
1178        }
1179        if (mDisplay == null) {
1180            WindowManager wm = WindowManagerImpl.getDefault();
1181            mDisplay = wm.getDefaultDisplay();
1182        }
1183        DisplayMetrics metrics = mDisplayMetrics = new DisplayMetrics();
1184        mDisplay.getMetrics(metrics);
1185        //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
1186        //        + metrics.heightPixels + " den=" + metrics.density
1187        //        + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
1188        return metrics;
1189    }
1190
1191    /**
1192     * Creates the top level Resources for applications with the given compatibility info.
1193     *
1194     * @param resDir the resource directory.
1195     * @param compInfo the compability info. It will use the default compatibility info when it's
1196     * null.
1197     */
1198    Resources getTopLevelResources(String resDir, CompatibilityInfo compInfo) {
1199        ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale);
1200        Resources r;
1201        synchronized (mPackages) {
1202            // Resources is app scale dependent.
1203            if (false) {
1204                Slog.w(TAG, "getTopLevelResources: " + resDir + " / "
1205                        + compInfo.applicationScale);
1206            }
1207            WeakReference<Resources> wr = mActiveResources.get(key);
1208            r = wr != null ? wr.get() : null;
1209            //if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
1210            if (r != null && r.getAssets().isUpToDate()) {
1211                if (false) {
1212                    Slog.w(TAG, "Returning cached resources " + r + " " + resDir
1213                            + ": appScale=" + r.getCompatibilityInfo().applicationScale);
1214                }
1215                return r;
1216            }
1217        }
1218
1219        //if (r != null) {
1220        //    Slog.w(TAG, "Throwing away out-of-date resources!!!! "
1221        //            + r + " " + resDir);
1222        //}
1223
1224        AssetManager assets = new AssetManager();
1225        if (assets.addAssetPath(resDir) == 0) {
1226            return null;
1227        }
1228
1229        //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
1230        DisplayMetrics metrics = getDisplayMetricsLocked(false);
1231        r = new Resources(assets, metrics, getConfiguration(), compInfo);
1232        if (false) {
1233            Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
1234                    + r.getConfiguration() + " appScale="
1235                    + r.getCompatibilityInfo().applicationScale);
1236        }
1237
1238        synchronized (mPackages) {
1239            WeakReference<Resources> wr = mActiveResources.get(key);
1240            Resources existing = wr != null ? wr.get() : null;
1241            if (existing != null && existing.getAssets().isUpToDate()) {
1242                // Someone else already created the resources while we were
1243                // unlocked; go ahead and use theirs.
1244                r.getAssets().close();
1245                return existing;
1246            }
1247
1248            // XXX need to remove entries when weak references go away
1249            mActiveResources.put(key, new WeakReference<Resources>(r));
1250            return r;
1251        }
1252    }
1253
1254    /**
1255     * Creates the top level resources for the given package.
1256     */
1257    Resources getTopLevelResources(String resDir, LoadedApk pkgInfo) {
1258        return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo);
1259    }
1260
1261    final Handler getHandler() {
1262        return mH;
1263    }
1264
1265    public final LoadedApk getPackageInfo(String packageName, int flags) {
1266        synchronized (mPackages) {
1267            WeakReference<LoadedApk> ref;
1268            if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) {
1269                ref = mPackages.get(packageName);
1270            } else {
1271                ref = mResourcePackages.get(packageName);
1272            }
1273            LoadedApk packageInfo = ref != null ? ref.get() : null;
1274            //Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo);
1275            //if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir
1276            //        + ": " + packageInfo.mResources.getAssets().isUpToDate());
1277            if (packageInfo != null && (packageInfo.mResources == null
1278                    || packageInfo.mResources.getAssets().isUpToDate())) {
1279                if (packageInfo.isSecurityViolation()
1280                        && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {
1281                    throw new SecurityException(
1282                            "Requesting code from " + packageName
1283                            + " to be run in process "
1284                            + mBoundApplication.processName
1285                            + "/" + mBoundApplication.appInfo.uid);
1286                }
1287                return packageInfo;
1288            }
1289        }
1290
1291        ApplicationInfo ai = null;
1292        try {
1293            ai = getPackageManager().getApplicationInfo(packageName,
1294                    PackageManager.GET_SHARED_LIBRARY_FILES);
1295        } catch (RemoteException e) {
1296        }
1297
1298        if (ai != null) {
1299            return getPackageInfo(ai, flags);
1300        }
1301
1302        return null;
1303    }
1304
1305    public final LoadedApk getPackageInfo(ApplicationInfo ai, int flags) {
1306        boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
1307        boolean securityViolation = includeCode && ai.uid != 0
1308                && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
1309                        ? ai.uid != mBoundApplication.appInfo.uid : true);
1310        if ((flags&(Context.CONTEXT_INCLUDE_CODE
1311                |Context.CONTEXT_IGNORE_SECURITY))
1312                == Context.CONTEXT_INCLUDE_CODE) {
1313            if (securityViolation) {
1314                String msg = "Requesting code from " + ai.packageName
1315                        + " (with uid " + ai.uid + ")";
1316                if (mBoundApplication != null) {
1317                    msg = msg + " to be run in process "
1318                        + mBoundApplication.processName + " (with uid "
1319                        + mBoundApplication.appInfo.uid + ")";
1320                }
1321                throw new SecurityException(msg);
1322            }
1323        }
1324        return getPackageInfo(ai, null, securityViolation, includeCode);
1325    }
1326
1327    public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai) {
1328        return getPackageInfo(ai, null, false, true);
1329    }
1330
1331    private final LoadedApk getPackageInfo(ApplicationInfo aInfo,
1332            ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
1333        synchronized (mPackages) {
1334            WeakReference<LoadedApk> ref;
1335            if (includeCode) {
1336                ref = mPackages.get(aInfo.packageName);
1337            } else {
1338                ref = mResourcePackages.get(aInfo.packageName);
1339            }
1340            LoadedApk packageInfo = ref != null ? ref.get() : null;
1341            if (packageInfo == null || (packageInfo.mResources != null
1342                    && !packageInfo.mResources.getAssets().isUpToDate())) {
1343                if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package "
1344                        : "Loading resource-only package ") + aInfo.packageName
1345                        + " (in " + (mBoundApplication != null
1346                                ? mBoundApplication.processName : null)
1347                        + ")");
1348                packageInfo =
1349                    new LoadedApk(this, aInfo, this, baseLoader,
1350                            securityViolation, includeCode &&
1351                            (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
1352                if (includeCode) {
1353                    mPackages.put(aInfo.packageName,
1354                            new WeakReference<LoadedApk>(packageInfo));
1355                } else {
1356                    mResourcePackages.put(aInfo.packageName,
1357                            new WeakReference<LoadedApk>(packageInfo));
1358                }
1359            }
1360            return packageInfo;
1361        }
1362    }
1363
1364    ActivityThread() {
1365    }
1366
1367    public ApplicationThread getApplicationThread()
1368    {
1369        return mAppThread;
1370    }
1371
1372    public Instrumentation getInstrumentation()
1373    {
1374        return mInstrumentation;
1375    }
1376
1377    public Configuration getConfiguration() {
1378        return mConfiguration;
1379    }
1380
1381    public boolean isProfiling() {
1382        return mBoundApplication != null && mBoundApplication.profileFile != null;
1383    }
1384
1385    public String getProfileFilePath() {
1386        return mBoundApplication.profileFile;
1387    }
1388
1389    public Looper getLooper() {
1390        return mLooper;
1391    }
1392
1393    public Application getApplication() {
1394        return mInitialApplication;
1395    }
1396
1397    public String getProcessName() {
1398        return mBoundApplication.processName;
1399    }
1400
1401    public ContextImpl getSystemContext() {
1402        synchronized (this) {
1403            if (mSystemContext == null) {
1404                ContextImpl context =
1405                    ContextImpl.createSystemContext(this);
1406                LoadedApk info = new LoadedApk(this, "android", context, null);
1407                context.init(info, null, this);
1408                context.getResources().updateConfiguration(
1409                        getConfiguration(), getDisplayMetricsLocked(false));
1410                mSystemContext = context;
1411                //Slog.i(TAG, "Created system resources " + context.getResources()
1412                //        + ": " + context.getResources().getConfiguration());
1413            }
1414        }
1415        return mSystemContext;
1416    }
1417
1418    public void installSystemApplicationInfo(ApplicationInfo info) {
1419        synchronized (this) {
1420            ContextImpl context = getSystemContext();
1421            context.init(new LoadedApk(this, "android", context, info), null, this);
1422        }
1423    }
1424
1425    void ensureJitEnabled() {
1426        if (!mJitEnabled) {
1427            mJitEnabled = true;
1428            dalvik.system.VMRuntime.getRuntime().startJitCompilation();
1429        }
1430    }
1431
1432    void scheduleGcIdler() {
1433        if (!mGcIdlerScheduled) {
1434            mGcIdlerScheduled = true;
1435            Looper.myQueue().addIdleHandler(mGcIdler);
1436        }
1437        mH.removeMessages(H.GC_WHEN_IDLE);
1438    }
1439
1440    void unscheduleGcIdler() {
1441        if (mGcIdlerScheduled) {
1442            mGcIdlerScheduled = false;
1443            Looper.myQueue().removeIdleHandler(mGcIdler);
1444        }
1445        mH.removeMessages(H.GC_WHEN_IDLE);
1446    }
1447
1448    void doGcIfNeeded() {
1449        mGcIdlerScheduled = false;
1450        final long now = SystemClock.uptimeMillis();
1451        //Slog.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime()
1452        //        + "m now=" + now);
1453        if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) {
1454            //Slog.i(TAG, "**** WE DO, WE DO WANT TO GC!");
1455            BinderInternal.forceGc("bg");
1456        }
1457    }
1458
1459    public final ActivityInfo resolveActivityInfo(Intent intent) {
1460        ActivityInfo aInfo = intent.resolveActivityInfo(
1461                mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES);
1462        if (aInfo == null) {
1463            // Throw an exception.
1464            Instrumentation.checkStartActivityResult(
1465                    IActivityManager.START_CLASS_NOT_FOUND, intent);
1466        }
1467        return aInfo;
1468    }
1469
1470    public final Activity startActivityNow(Activity parent, String id,
1471        Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
1472        Activity.NonConfigurationInstances lastNonConfigurationInstances) {
1473        ActivityClientRecord r = new ActivityClientRecord();
1474            r.token = token;
1475            r.ident = 0;
1476            r.intent = intent;
1477            r.state = state;
1478            r.parent = parent;
1479            r.embeddedID = id;
1480            r.activityInfo = activityInfo;
1481            r.lastNonConfigurationInstances = lastNonConfigurationInstances;
1482        if (localLOGV) {
1483            ComponentName compname = intent.getComponent();
1484            String name;
1485            if (compname != null) {
1486                name = compname.toShortString();
1487            } else {
1488                name = "(Intent " + intent + ").getComponent() returned null";
1489            }
1490            Slog.v(TAG, "Performing launch: action=" + intent.getAction()
1491                    + ", comp=" + name
1492                    + ", token=" + token);
1493        }
1494        return performLaunchActivity(r, null);
1495    }
1496
1497    public final Activity getActivity(IBinder token) {
1498        return mActivities.get(token).activity;
1499    }
1500
1501    public final void sendActivityResult(
1502            IBinder token, String id, int requestCode,
1503            int resultCode, Intent data) {
1504        if (DEBUG_RESULTS) Slog.v(TAG, "sendActivityResult: id=" + id
1505                + " req=" + requestCode + " res=" + resultCode + " data=" + data);
1506        ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
1507        list.add(new ResultInfo(id, requestCode, resultCode, data));
1508        mAppThread.scheduleSendResult(token, list);
1509    }
1510
1511    // if the thread hasn't started yet, we don't have the handler, so just
1512    // save the messages until we're ready.
1513    private final void queueOrSendMessage(int what, Object obj) {
1514        queueOrSendMessage(what, obj, 0, 0);
1515    }
1516
1517    private final void queueOrSendMessage(int what, Object obj, int arg1) {
1518        queueOrSendMessage(what, obj, arg1, 0);
1519    }
1520
1521    private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
1522        synchronized (this) {
1523            if (localLOGV) Slog.v(
1524                TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
1525                + ": " + arg1 + " / " + obj);
1526            Message msg = Message.obtain();
1527            msg.what = what;
1528            msg.obj = obj;
1529            msg.arg1 = arg1;
1530            msg.arg2 = arg2;
1531            mH.sendMessage(msg);
1532        }
1533    }
1534
1535    final void scheduleContextCleanup(ContextImpl context, String who,
1536            String what) {
1537        ContextCleanupInfo cci = new ContextCleanupInfo();
1538        cci.context = context;
1539        cci.who = who;
1540        cci.what = what;
1541        queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci);
1542    }
1543
1544    private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
1545        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
1546
1547        ActivityInfo aInfo = r.activityInfo;
1548        if (r.packageInfo == null) {
1549            r.packageInfo = getPackageInfo(aInfo.applicationInfo,
1550                    Context.CONTEXT_INCLUDE_CODE);
1551        }
1552
1553        ComponentName component = r.intent.getComponent();
1554        if (component == null) {
1555            component = r.intent.resolveActivity(
1556                mInitialApplication.getPackageManager());
1557            r.intent.setComponent(component);
1558        }
1559
1560        if (r.activityInfo.targetActivity != null) {
1561            component = new ComponentName(r.activityInfo.packageName,
1562                    r.activityInfo.targetActivity);
1563        }
1564
1565        Activity activity = null;
1566        try {
1567            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
1568            activity = mInstrumentation.newActivity(
1569                    cl, component.getClassName(), r.intent);
1570            r.intent.setExtrasClassLoader(cl);
1571            if (r.state != null) {
1572                r.state.setClassLoader(cl);
1573            }
1574        } catch (Exception e) {
1575            if (!mInstrumentation.onException(activity, e)) {
1576                throw new RuntimeException(
1577                    "Unable to instantiate activity " + component
1578                    + ": " + e.toString(), e);
1579            }
1580        }
1581
1582        try {
1583            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
1584
1585            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
1586            if (localLOGV) Slog.v(
1587                    TAG, r + ": app=" + app
1588                    + ", appName=" + app.getPackageName()
1589                    + ", pkg=" + r.packageInfo.getPackageName()
1590                    + ", comp=" + r.intent.getComponent().toShortString()
1591                    + ", dir=" + r.packageInfo.getAppDir());
1592
1593            if (activity != null) {
1594                ContextImpl appContext = new ContextImpl();
1595                appContext.init(r.packageInfo, r.token, this);
1596                appContext.setOuterContext(activity);
1597                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
1598                Configuration config = new Configuration(mConfiguration);
1599                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
1600                        + r.activityInfo.name + " with config " + config);
1601                activity.attach(appContext, this, getInstrumentation(), r.token,
1602                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
1603                        r.embeddedID, r.lastNonConfigurationInstances, config);
1604
1605                if (customIntent != null) {
1606                    activity.mIntent = customIntent;
1607                }
1608                r.lastNonConfigurationInstances = null;
1609                activity.mStartedActivity = false;
1610                int theme = r.activityInfo.getThemeResource();
1611                if (theme != 0) {
1612                    activity.setTheme(theme);
1613                }
1614
1615                activity.mCalled = false;
1616                mInstrumentation.callActivityOnCreate(activity, r.state);
1617                if (!activity.mCalled) {
1618                    throw new SuperNotCalledException(
1619                        "Activity " + r.intent.getComponent().toShortString() +
1620                        " did not call through to super.onCreate()");
1621                }
1622                r.activity = activity;
1623                r.stopped = true;
1624                if (!r.activity.mFinished) {
1625                    activity.performStart();
1626                    r.stopped = false;
1627                }
1628                if (!r.activity.mFinished) {
1629                    if (r.state != null) {
1630                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
1631                    }
1632                }
1633                if (!r.activity.mFinished) {
1634                    activity.mCalled = false;
1635                    mInstrumentation.callActivityOnPostCreate(activity, r.state);
1636                    if (!activity.mCalled) {
1637                        throw new SuperNotCalledException(
1638                            "Activity " + r.intent.getComponent().toShortString() +
1639                            " did not call through to super.onPostCreate()");
1640                    }
1641                }
1642            }
1643            r.paused = true;
1644
1645            mActivities.put(r.token, r);
1646
1647        } catch (SuperNotCalledException e) {
1648            throw e;
1649
1650        } catch (Exception e) {
1651            if (!mInstrumentation.onException(activity, e)) {
1652                throw new RuntimeException(
1653                    "Unable to start activity " + component
1654                    + ": " + e.toString(), e);
1655            }
1656        }
1657
1658        return activity;
1659    }
1660
1661    private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
1662        // If we are getting ready to gc after going to the background, well
1663        // we are back active so skip it.
1664        unscheduleGcIdler();
1665
1666        if (localLOGV) Slog.v(
1667            TAG, "Handling launch of " + r);
1668        Activity a = performLaunchActivity(r, customIntent);
1669
1670        if (a != null) {
1671            r.createdConfig = new Configuration(mConfiguration);
1672            Bundle oldState = r.state;
1673            handleResumeActivity(r.token, false, r.isForward);
1674
1675            if (!r.activity.mFinished && r.startsNotResumed) {
1676                // The activity manager actually wants this one to start out
1677                // paused, because it needs to be visible but isn't in the
1678                // foreground.  We accomplish this by going through the
1679                // normal startup (because activities expect to go through
1680                // onResume() the first time they run, before their window
1681                // is displayed), and then pausing it.  However, in this case
1682                // we do -not- need to do the full pause cycle (of freezing
1683                // and such) because the activity manager assumes it can just
1684                // retain the current state it has.
1685                try {
1686                    r.activity.mCalled = false;
1687                    mInstrumentation.callActivityOnPause(r.activity);
1688                    // We need to keep around the original state, in case
1689                    // we need to be created again.
1690                    r.state = oldState;
1691                    if (!r.activity.mCalled) {
1692                        throw new SuperNotCalledException(
1693                            "Activity " + r.intent.getComponent().toShortString() +
1694                            " did not call through to super.onPause()");
1695                    }
1696
1697                } catch (SuperNotCalledException e) {
1698                    throw e;
1699
1700                } catch (Exception e) {
1701                    if (!mInstrumentation.onException(r.activity, e)) {
1702                        throw new RuntimeException(
1703                                "Unable to pause activity "
1704                                + r.intent.getComponent().toShortString()
1705                                + ": " + e.toString(), e);
1706                    }
1707                }
1708                r.paused = true;
1709            }
1710        } else {
1711            // If there was an error, for any reason, tell the activity
1712            // manager to stop us.
1713            try {
1714                ActivityManagerNative.getDefault()
1715                    .finishActivity(r.token, Activity.RESULT_CANCELED, null);
1716            } catch (RemoteException ex) {
1717            }
1718        }
1719    }
1720
1721    private final void deliverNewIntents(ActivityClientRecord r,
1722            List<Intent> intents) {
1723        final int N = intents.size();
1724        for (int i=0; i<N; i++) {
1725            Intent intent = intents.get(i);
1726            intent.setExtrasClassLoader(r.activity.getClassLoader());
1727            mInstrumentation.callActivityOnNewIntent(r.activity, intent);
1728        }
1729    }
1730
1731    public final void performNewIntents(IBinder token,
1732            List<Intent> intents) {
1733        ActivityClientRecord r = mActivities.get(token);
1734        if (r != null) {
1735            final boolean resumed = !r.paused;
1736            if (resumed) {
1737                mInstrumentation.callActivityOnPause(r.activity);
1738            }
1739            deliverNewIntents(r, intents);
1740            if (resumed) {
1741                mInstrumentation.callActivityOnResume(r.activity);
1742            }
1743        }
1744    }
1745
1746    private final void handleNewIntent(NewIntentData data) {
1747        performNewIntents(data.token, data.intents);
1748    }
1749
1750    private final void handleReceiver(ReceiverData data) {
1751        // If we are getting ready to gc after going to the background, well
1752        // we are back active so skip it.
1753        unscheduleGcIdler();
1754
1755        String component = data.intent.getComponent().getClassName();
1756
1757        LoadedApk packageInfo = getPackageInfoNoCheck(
1758                data.info.applicationInfo);
1759
1760        IActivityManager mgr = ActivityManagerNative.getDefault();
1761
1762        BroadcastReceiver receiver = null;
1763        try {
1764            java.lang.ClassLoader cl = packageInfo.getClassLoader();
1765            data.intent.setExtrasClassLoader(cl);
1766            if (data.resultExtras != null) {
1767                data.resultExtras.setClassLoader(cl);
1768            }
1769            receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
1770        } catch (Exception e) {
1771            try {
1772                if (DEBUG_BROADCAST) Slog.i(TAG,
1773                        "Finishing failed broadcast to " + data.intent.getComponent());
1774                mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
1775                                   data.resultData, data.resultExtras, data.resultAbort);
1776            } catch (RemoteException ex) {
1777            }
1778            throw new RuntimeException(
1779                "Unable to instantiate receiver " + component
1780                + ": " + e.toString(), e);
1781        }
1782
1783        try {
1784            Application app = packageInfo.makeApplication(false, mInstrumentation);
1785
1786            if (localLOGV) Slog.v(
1787                TAG, "Performing receive of " + data.intent
1788                + ": app=" + app
1789                + ", appName=" + app.getPackageName()
1790                + ", pkg=" + packageInfo.getPackageName()
1791                + ", comp=" + data.intent.getComponent().toShortString()
1792                + ", dir=" + packageInfo.getAppDir());
1793
1794            ContextImpl context = (ContextImpl)app.getBaseContext();
1795            receiver.setOrderedHint(true);
1796            receiver.setResult(data.resultCode, data.resultData,
1797                data.resultExtras);
1798            receiver.setOrderedHint(data.sync);
1799            receiver.onReceive(context.getReceiverRestrictedContext(),
1800                    data.intent);
1801        } catch (Exception e) {
1802            try {
1803                if (DEBUG_BROADCAST) Slog.i(TAG,
1804                        "Finishing failed broadcast to " + data.intent.getComponent());
1805                mgr.finishReceiver(mAppThread.asBinder(), data.resultCode,
1806                    data.resultData, data.resultExtras, data.resultAbort);
1807            } catch (RemoteException ex) {
1808            }
1809            if (!mInstrumentation.onException(receiver, e)) {
1810                throw new RuntimeException(
1811                    "Unable to start receiver " + component
1812                    + ": " + e.toString(), e);
1813            }
1814        }
1815
1816        QueuedWork.waitToFinish();
1817
1818        try {
1819            if (data.sync) {
1820                if (DEBUG_BROADCAST) Slog.i(TAG,
1821                        "Finishing ordered broadcast to " + data.intent.getComponent());
1822                mgr.finishReceiver(
1823                    mAppThread.asBinder(), receiver.getResultCode(),
1824                    receiver.getResultData(), receiver.getResultExtras(false),
1825                        receiver.getAbortBroadcast());
1826            } else {
1827                if (DEBUG_BROADCAST) Slog.i(TAG,
1828                        "Finishing broadcast to " + data.intent.getComponent());
1829                mgr.finishReceiver(mAppThread.asBinder(), 0, null, null, false);
1830            }
1831        } catch (RemoteException ex) {
1832        }
1833    }
1834
1835    // Instantiate a BackupAgent and tell it that it's alive
1836    private final void handleCreateBackupAgent(CreateBackupAgentData data) {
1837        if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data);
1838
1839        // no longer idle; we have backup work to do
1840        unscheduleGcIdler();
1841
1842        // instantiate the BackupAgent class named in the manifest
1843        LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo);
1844        String packageName = packageInfo.mPackageName;
1845        if (mBackupAgents.get(packageName) != null) {
1846            Slog.d(TAG, "BackupAgent " + "  for " + packageName
1847                    + " already exists");
1848            return;
1849        }
1850
1851        BackupAgent agent = null;
1852        String classname = data.appInfo.backupAgentName;
1853        if (classname == null) {
1854            if (data.backupMode == IApplicationThread.BACKUP_MODE_INCREMENTAL) {
1855                Slog.e(TAG, "Attempted incremental backup but no defined agent for "
1856                        + packageName);
1857                return;
1858            }
1859            classname = "android.app.FullBackupAgent";
1860        }
1861        try {
1862            IBinder binder = null;
1863            try {
1864                java.lang.ClassLoader cl = packageInfo.getClassLoader();
1865                agent = (BackupAgent) cl.loadClass(data.appInfo.backupAgentName).newInstance();
1866
1867                // set up the agent's context
1868                if (DEBUG_BACKUP) Slog.v(TAG, "Initializing BackupAgent "
1869                        + data.appInfo.backupAgentName);
1870
1871                ContextImpl context = new ContextImpl();
1872                context.init(packageInfo, null, this);
1873                context.setOuterContext(agent);
1874                agent.attach(context);
1875
1876                agent.onCreate();
1877                binder = agent.onBind();
1878                mBackupAgents.put(packageName, agent);
1879            } catch (Exception e) {
1880                // If this is during restore, fail silently; otherwise go
1881                // ahead and let the user see the crash.
1882                Slog.e(TAG, "Agent threw during creation: " + e);
1883                if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE) {
1884                    throw e;
1885                }
1886                // falling through with 'binder' still null
1887            }
1888
1889            // tell the OS that we're live now
1890            try {
1891                ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder);
1892            } catch (RemoteException e) {
1893                // nothing to do.
1894            }
1895        } catch (Exception e) {
1896            throw new RuntimeException("Unable to create BackupAgent "
1897                    + data.appInfo.backupAgentName + ": " + e.toString(), e);
1898        }
1899    }
1900
1901    // Tear down a BackupAgent
1902    private final void handleDestroyBackupAgent(CreateBackupAgentData data) {
1903        if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
1904
1905        LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo);
1906        String packageName = packageInfo.mPackageName;
1907        BackupAgent agent = mBackupAgents.get(packageName);
1908        if (agent != null) {
1909            try {
1910                agent.onDestroy();
1911            } catch (Exception e) {
1912                Slog.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo);
1913                e.printStackTrace();
1914            }
1915            mBackupAgents.remove(packageName);
1916        } else {
1917            Slog.w(TAG, "Attempt to destroy unknown backup agent " + data);
1918        }
1919    }
1920
1921    private final void handleCreateService(CreateServiceData data) {
1922        // If we are getting ready to gc after going to the background, well
1923        // we are back active so skip it.
1924        unscheduleGcIdler();
1925
1926        LoadedApk packageInfo = getPackageInfoNoCheck(
1927                data.info.applicationInfo);
1928        Service service = null;
1929        try {
1930            java.lang.ClassLoader cl = packageInfo.getClassLoader();
1931            service = (Service) cl.loadClass(data.info.name).newInstance();
1932        } catch (Exception e) {
1933            if (!mInstrumentation.onException(service, e)) {
1934                throw new RuntimeException(
1935                    "Unable to instantiate service " + data.info.name
1936                    + ": " + e.toString(), e);
1937            }
1938        }
1939
1940        try {
1941            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
1942
1943            ContextImpl context = new ContextImpl();
1944            context.init(packageInfo, null, this);
1945
1946            Application app = packageInfo.makeApplication(false, mInstrumentation);
1947            context.setOuterContext(service);
1948            service.attach(context, this, data.info.name, data.token, app,
1949                    ActivityManagerNative.getDefault());
1950            service.onCreate();
1951            mServices.put(data.token, service);
1952            try {
1953                ActivityManagerNative.getDefault().serviceDoneExecuting(
1954                        data.token, 0, 0, 0);
1955            } catch (RemoteException e) {
1956                // nothing to do.
1957            }
1958        } catch (Exception e) {
1959            if (!mInstrumentation.onException(service, e)) {
1960                throw new RuntimeException(
1961                    "Unable to create service " + data.info.name
1962                    + ": " + e.toString(), e);
1963            }
1964        }
1965    }
1966
1967    private final void handleBindService(BindServiceData data) {
1968        Service s = mServices.get(data.token);
1969        if (s != null) {
1970            try {
1971                data.intent.setExtrasClassLoader(s.getClassLoader());
1972                try {
1973                    if (!data.rebind) {
1974                        IBinder binder = s.onBind(data.intent);
1975                        ActivityManagerNative.getDefault().publishService(
1976                                data.token, data.intent, binder);
1977                    } else {
1978                        s.onRebind(data.intent);
1979                        ActivityManagerNative.getDefault().serviceDoneExecuting(
1980                                data.token, 0, 0, 0);
1981                    }
1982                    ensureJitEnabled();
1983                } catch (RemoteException ex) {
1984                }
1985            } catch (Exception e) {
1986                if (!mInstrumentation.onException(s, e)) {
1987                    throw new RuntimeException(
1988                            "Unable to bind to service " + s
1989                            + " with " + data.intent + ": " + e.toString(), e);
1990                }
1991            }
1992        }
1993    }
1994
1995    private final void handleUnbindService(BindServiceData data) {
1996        Service s = mServices.get(data.token);
1997        if (s != null) {
1998            try {
1999                data.intent.setExtrasClassLoader(s.getClassLoader());
2000                boolean doRebind = s.onUnbind(data.intent);
2001                try {
2002                    if (doRebind) {
2003                        ActivityManagerNative.getDefault().unbindFinished(
2004                                data.token, data.intent, doRebind);
2005                    } else {
2006                        ActivityManagerNative.getDefault().serviceDoneExecuting(
2007                                data.token, 0, 0, 0);
2008                    }
2009                } catch (RemoteException ex) {
2010                }
2011            } catch (Exception e) {
2012                if (!mInstrumentation.onException(s, e)) {
2013                    throw new RuntimeException(
2014                            "Unable to unbind to service " + s
2015                            + " with " + data.intent + ": " + e.toString(), e);
2016                }
2017            }
2018        }
2019    }
2020
2021    private void handleDumpService(DumpServiceInfo info) {
2022        try {
2023            Service s = mServices.get(info.service);
2024            if (s != null) {
2025                PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd));
2026                s.dump(info.fd, pw, info.args);
2027                pw.close();
2028            }
2029        } finally {
2030            synchronized (info) {
2031                info.dumped = true;
2032                info.notifyAll();
2033            }
2034        }
2035    }
2036
2037    private final void handleServiceArgs(ServiceArgsData data) {
2038        Service s = mServices.get(data.token);
2039        if (s != null) {
2040            try {
2041                if (data.args != null) {
2042                    data.args.setExtrasClassLoader(s.getClassLoader());
2043                }
2044                int res = s.onStartCommand(data.args, data.flags, data.startId);
2045
2046                QueuedWork.waitToFinish();
2047
2048                try {
2049                    ActivityManagerNative.getDefault().serviceDoneExecuting(
2050                            data.token, 1, data.startId, res);
2051                } catch (RemoteException e) {
2052                    // nothing to do.
2053                }
2054                ensureJitEnabled();
2055            } catch (Exception e) {
2056                if (!mInstrumentation.onException(s, e)) {
2057                    throw new RuntimeException(
2058                            "Unable to start service " + s
2059                            + " with " + data.args + ": " + e.toString(), e);
2060                }
2061            }
2062        }
2063    }
2064
2065    private final void handleStopService(IBinder token) {
2066        Service s = mServices.remove(token);
2067        if (s != null) {
2068            try {
2069                if (localLOGV) Slog.v(TAG, "Destroying service " + s);
2070                s.onDestroy();
2071                Context context = s.getBaseContext();
2072                if (context instanceof ContextImpl) {
2073                    final String who = s.getClassName();
2074                    ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
2075                }
2076
2077                QueuedWork.waitToFinish();
2078
2079                try {
2080                    ActivityManagerNative.getDefault().serviceDoneExecuting(
2081                            token, 0, 0, 0);
2082                } catch (RemoteException e) {
2083                    // nothing to do.
2084                }
2085            } catch (Exception e) {
2086                if (!mInstrumentation.onException(s, e)) {
2087                    throw new RuntimeException(
2088                            "Unable to stop service " + s
2089                            + ": " + e.toString(), e);
2090                }
2091            }
2092        }
2093        //Slog.i(TAG, "Running services: " + mServices);
2094    }
2095
2096    public final ActivityClientRecord performResumeActivity(IBinder token,
2097            boolean clearHide) {
2098        ActivityClientRecord r = mActivities.get(token);
2099        if (localLOGV) Slog.v(TAG, "Performing resume of " + r
2100                + " finished=" + r.activity.mFinished);
2101        if (r != null && !r.activity.mFinished) {
2102            if (clearHide) {
2103                r.hideForNow = false;
2104                r.activity.mStartedActivity = false;
2105            }
2106            try {
2107                if (r.pendingIntents != null) {
2108                    deliverNewIntents(r, r.pendingIntents);
2109                    r.pendingIntents = null;
2110                }
2111                if (r.pendingResults != null) {
2112                    deliverResults(r, r.pendingResults);
2113                    r.pendingResults = null;
2114                }
2115                r.activity.performResume();
2116
2117                EventLog.writeEvent(LOG_ON_RESUME_CALLED,
2118                        r.activity.getComponentName().getClassName());
2119
2120                r.paused = false;
2121                r.stopped = false;
2122                r.state = null;
2123            } catch (Exception e) {
2124                if (!mInstrumentation.onException(r.activity, e)) {
2125                    throw new RuntimeException(
2126                        "Unable to resume activity "
2127                        + r.intent.getComponent().toShortString()
2128                        + ": " + e.toString(), e);
2129                }
2130            }
2131        }
2132        return r;
2133    }
2134
2135    final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
2136        // If we are getting ready to gc after going to the background, well
2137        // we are back active so skip it.
2138        unscheduleGcIdler();
2139
2140        ActivityClientRecord r = performResumeActivity(token, clearHide);
2141
2142        if (r != null) {
2143            final Activity a = r.activity;
2144
2145            if (localLOGV) Slog.v(
2146                TAG, "Resume " + r + " started activity: " +
2147                a.mStartedActivity + ", hideForNow: " + r.hideForNow
2148                + ", finished: " + a.mFinished);
2149
2150            final int forwardBit = isForward ?
2151                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
2152
2153            // If the window hasn't yet been added to the window manager,
2154            // and this guy didn't finish itself or start another activity,
2155            // then go ahead and add the window.
2156            boolean willBeVisible = !a.mStartedActivity;
2157            if (!willBeVisible) {
2158                try {
2159                    willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
2160                            a.getActivityToken());
2161                } catch (RemoteException e) {
2162                }
2163            }
2164            if (r.window == null && !a.mFinished && willBeVisible) {
2165                r.window = r.activity.getWindow();
2166                View decor = r.window.getDecorView();
2167                decor.setVisibility(View.INVISIBLE);
2168                ViewManager wm = a.getWindowManager();
2169                WindowManager.LayoutParams l = r.window.getAttributes();
2170                a.mDecor = decor;
2171                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
2172                l.softInputMode |= forwardBit;
2173                if (a.mVisibleFromClient) {
2174                    a.mWindowAdded = true;
2175                    wm.addView(decor, l);
2176                }
2177
2178            // If the window has already been added, but during resume
2179            // we started another activity, then don't yet make the
2180            // window visible.
2181            } else if (!willBeVisible) {
2182                if (localLOGV) Slog.v(
2183                    TAG, "Launch " + r + " mStartedActivity set");
2184                r.hideForNow = true;
2185            }
2186
2187            // The window is now visible if it has been added, we are not
2188            // simply finishing, and we are not starting another activity.
2189            if (!r.activity.mFinished && willBeVisible
2190                    && r.activity.mDecor != null && !r.hideForNow) {
2191                if (r.newConfig != null) {
2192                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
2193                            + r.activityInfo.name + " with newConfig " + r.newConfig);
2194                    performConfigurationChanged(r.activity, r.newConfig);
2195                    r.newConfig = null;
2196                }
2197                if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
2198                        + isForward);
2199                WindowManager.LayoutParams l = r.window.getAttributes();
2200                if ((l.softInputMode
2201                        & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
2202                        != forwardBit) {
2203                    l.softInputMode = (l.softInputMode
2204                            & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
2205                            | forwardBit;
2206                    if (r.activity.mVisibleFromClient) {
2207                        ViewManager wm = a.getWindowManager();
2208                        View decor = r.window.getDecorView();
2209                        wm.updateViewLayout(decor, l);
2210                    }
2211                }
2212                r.activity.mVisibleFromServer = true;
2213                mNumVisibleActivities++;
2214                if (r.activity.mVisibleFromClient) {
2215                    r.activity.makeVisible();
2216                }
2217            }
2218
2219            r.nextIdle = mNewActivities;
2220            mNewActivities = r;
2221            if (localLOGV) Slog.v(
2222                TAG, "Scheduling idle handler for " + r);
2223            Looper.myQueue().addIdleHandler(new Idler());
2224
2225        } else {
2226            // If an exception was thrown when trying to resume, then
2227            // just end this activity.
2228            try {
2229                ActivityManagerNative.getDefault()
2230                    .finishActivity(token, Activity.RESULT_CANCELED, null);
2231            } catch (RemoteException ex) {
2232            }
2233        }
2234    }
2235
2236    private int mThumbnailWidth = -1;
2237    private int mThumbnailHeight = -1;
2238
2239    private final Bitmap createThumbnailBitmap(ActivityClientRecord r) {
2240        Bitmap thumbnail = null;
2241        try {
2242            int w = mThumbnailWidth;
2243            int h;
2244            if (w < 0) {
2245                Resources res = r.activity.getResources();
2246                mThumbnailHeight = h =
2247                    res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
2248
2249                mThumbnailWidth = w =
2250                    res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
2251            } else {
2252                h = mThumbnailHeight;
2253            }
2254
2255            // On platforms where we don't want thumbnails, set dims to (0,0)
2256            if ((w > 0) && (h > 0)) {
2257                View topView = r.activity.getWindow().getDecorView();
2258
2259                // Maximize bitmap by capturing in native aspect.
2260                if (topView.getWidth() >= topView.getHeight()) {
2261                    thumbnail = Bitmap.createBitmap(w, h, THUMBNAIL_FORMAT);
2262                } else {
2263                    thumbnail = Bitmap.createBitmap(h, w, THUMBNAIL_FORMAT);
2264                }
2265
2266                thumbnail.eraseColor(0);
2267                Canvas cv = new Canvas(thumbnail);
2268                if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
2269                    thumbnail = null;
2270                }
2271            }
2272
2273        } catch (Exception e) {
2274            if (!mInstrumentation.onException(r.activity, e)) {
2275                throw new RuntimeException(
2276                        "Unable to create thumbnail of "
2277                        + r.intent.getComponent().toShortString()
2278                        + ": " + e.toString(), e);
2279            }
2280            thumbnail = null;
2281        }
2282
2283        return thumbnail;
2284    }
2285
2286    private final void handlePauseActivity(IBinder token, boolean finished,
2287            boolean userLeaving, int configChanges) {
2288        ActivityClientRecord r = mActivities.get(token);
2289        if (r != null) {
2290            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
2291            if (userLeaving) {
2292                performUserLeavingActivity(r);
2293            }
2294
2295            r.activity.mConfigChangeFlags |= configChanges;
2296            Bundle state = performPauseActivity(token, finished, true);
2297
2298            // Tell the activity manager we have paused.
2299            try {
2300                ActivityManagerNative.getDefault().activityPaused(token, state);
2301            } catch (RemoteException ex) {
2302            }
2303        }
2304    }
2305
2306    final void performUserLeavingActivity(ActivityClientRecord r) {
2307        mInstrumentation.callActivityOnUserLeaving(r.activity);
2308    }
2309
2310    final Bundle performPauseActivity(IBinder token, boolean finished,
2311            boolean saveState) {
2312        ActivityClientRecord r = mActivities.get(token);
2313        return r != null ? performPauseActivity(r, finished, saveState) : null;
2314    }
2315
2316    final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
2317            boolean saveState) {
2318        if (r.paused) {
2319            if (r.activity.mFinished) {
2320                // If we are finishing, we won't call onResume() in certain cases.
2321                // So here we likewise don't want to call onPause() if the activity
2322                // isn't resumed.
2323                return null;
2324            }
2325            RuntimeException e = new RuntimeException(
2326                    "Performing pause of activity that is not resumed: "
2327                    + r.intent.getComponent().toShortString());
2328            Slog.e(TAG, e.getMessage(), e);
2329        }
2330        Bundle state = null;
2331        if (finished) {
2332            r.activity.mFinished = true;
2333        }
2334        try {
2335            // Next have the activity save its current state and managed dialogs...
2336            if (!r.activity.mFinished && saveState) {
2337                state = new Bundle();
2338                mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
2339                r.state = state;
2340            }
2341            // Now we are idle.
2342            r.activity.mCalled = false;
2343            mInstrumentation.callActivityOnPause(r.activity);
2344            EventLog.writeEvent(LOG_ON_PAUSE_CALLED, r.activity.getComponentName().getClassName());
2345            if (!r.activity.mCalled) {
2346                throw new SuperNotCalledException(
2347                    "Activity " + r.intent.getComponent().toShortString() +
2348                    " did not call through to super.onPause()");
2349            }
2350
2351        } catch (SuperNotCalledException e) {
2352            throw e;
2353
2354        } catch (Exception e) {
2355            if (!mInstrumentation.onException(r.activity, e)) {
2356                throw new RuntimeException(
2357                        "Unable to pause activity "
2358                        + r.intent.getComponent().toShortString()
2359                        + ": " + e.toString(), e);
2360            }
2361        }
2362        r.paused = true;
2363        return state;
2364    }
2365
2366    final void performStopActivity(IBinder token) {
2367        ActivityClientRecord r = mActivities.get(token);
2368        performStopActivityInner(r, null, false);
2369    }
2370
2371    private static class StopInfo {
2372        Bitmap thumbnail;
2373        CharSequence description;
2374    }
2375
2376    private final class ProviderRefCount {
2377        public int count;
2378        ProviderRefCount(int pCount) {
2379            count = pCount;
2380        }
2381    }
2382
2383    private final void performStopActivityInner(ActivityClientRecord r,
2384            StopInfo info, boolean keepShown) {
2385        if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
2386        if (r != null) {
2387            if (!keepShown && r.stopped) {
2388                if (r.activity.mFinished) {
2389                    // If we are finishing, we won't call onResume() in certain
2390                    // cases.  So here we likewise don't want to call onStop()
2391                    // if the activity isn't resumed.
2392                    return;
2393                }
2394                RuntimeException e = new RuntimeException(
2395                        "Performing stop of activity that is not resumed: "
2396                        + r.intent.getComponent().toShortString());
2397                Slog.e(TAG, e.getMessage(), e);
2398            }
2399
2400            if (info != null) {
2401                try {
2402                    // First create a thumbnail for the activity...
2403                    info.thumbnail = createThumbnailBitmap(r);
2404                    info.description = r.activity.onCreateDescription();
2405                } catch (Exception e) {
2406                    if (!mInstrumentation.onException(r.activity, e)) {
2407                        throw new RuntimeException(
2408                                "Unable to save state of activity "
2409                                + r.intent.getComponent().toShortString()
2410                                + ": " + e.toString(), e);
2411                    }
2412                }
2413            }
2414
2415            if (!keepShown) {
2416                try {
2417                    // Now we are idle.
2418                    r.activity.performStop();
2419                } catch (Exception e) {
2420                    if (!mInstrumentation.onException(r.activity, e)) {
2421                        throw new RuntimeException(
2422                                "Unable to stop activity "
2423                                + r.intent.getComponent().toShortString()
2424                                + ": " + e.toString(), e);
2425                    }
2426                }
2427                r.stopped = true;
2428            }
2429
2430            r.paused = true;
2431        }
2432    }
2433
2434    private final void updateVisibility(ActivityClientRecord r, boolean show) {
2435        View v = r.activity.mDecor;
2436        if (v != null) {
2437            if (show) {
2438                if (!r.activity.mVisibleFromServer) {
2439                    r.activity.mVisibleFromServer = true;
2440                    mNumVisibleActivities++;
2441                    if (r.activity.mVisibleFromClient) {
2442                        r.activity.makeVisible();
2443                    }
2444                }
2445                if (r.newConfig != null) {
2446                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
2447                            + r.activityInfo.name + " with new config " + r.newConfig);
2448                    performConfigurationChanged(r.activity, r.newConfig);
2449                    r.newConfig = null;
2450                }
2451            } else {
2452                if (r.activity.mVisibleFromServer) {
2453                    r.activity.mVisibleFromServer = false;
2454                    mNumVisibleActivities--;
2455                    v.setVisibility(View.INVISIBLE);
2456                }
2457            }
2458        }
2459    }
2460
2461    private final void handleStopActivity(IBinder token, boolean show, int configChanges) {
2462        ActivityClientRecord r = mActivities.get(token);
2463        r.activity.mConfigChangeFlags |= configChanges;
2464
2465        StopInfo info = new StopInfo();
2466        performStopActivityInner(r, info, show);
2467
2468        if (localLOGV) Slog.v(
2469            TAG, "Finishing stop of " + r + ": show=" + show
2470            + " win=" + r.window);
2471
2472        updateVisibility(r, show);
2473
2474        // Tell activity manager we have been stopped.
2475        try {
2476            ActivityManagerNative.getDefault().activityStopped(
2477                r.token, info.thumbnail, info.description);
2478        } catch (RemoteException ex) {
2479        }
2480    }
2481
2482    final void performRestartActivity(IBinder token) {
2483        ActivityClientRecord r = mActivities.get(token);
2484        if (r.stopped) {
2485            r.activity.performRestart();
2486            r.stopped = false;
2487        }
2488    }
2489
2490    private final void handleWindowVisibility(IBinder token, boolean show) {
2491        ActivityClientRecord r = mActivities.get(token);
2492        if (!show && !r.stopped) {
2493            performStopActivityInner(r, null, show);
2494        } else if (show && r.stopped) {
2495            // If we are getting ready to gc after going to the background, well
2496            // we are back active so skip it.
2497            unscheduleGcIdler();
2498
2499            r.activity.performRestart();
2500            r.stopped = false;
2501        }
2502        if (r.activity.mDecor != null) {
2503            if (Config.LOGV) Slog.v(
2504                TAG, "Handle window " + r + " visibility: " + show);
2505            updateVisibility(r, show);
2506        }
2507    }
2508
2509    private final void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
2510        final int N = results.size();
2511        for (int i=0; i<N; i++) {
2512            ResultInfo ri = results.get(i);
2513            try {
2514                if (ri.mData != null) {
2515                    ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
2516                }
2517                if (DEBUG_RESULTS) Slog.v(TAG,
2518                        "Delivering result to activity " + r + " : " + ri);
2519                r.activity.dispatchActivityResult(ri.mResultWho,
2520                        ri.mRequestCode, ri.mResultCode, ri.mData);
2521            } catch (Exception e) {
2522                if (!mInstrumentation.onException(r.activity, e)) {
2523                    throw new RuntimeException(
2524                            "Failure delivering result " + ri + " to activity "
2525                            + r.intent.getComponent().toShortString()
2526                            + ": " + e.toString(), e);
2527                }
2528            }
2529        }
2530    }
2531
2532    private final void handleSendResult(ResultData res) {
2533        ActivityClientRecord r = mActivities.get(res.token);
2534        if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
2535        if (r != null) {
2536            final boolean resumed = !r.paused;
2537            if (!r.activity.mFinished && r.activity.mDecor != null
2538                    && r.hideForNow && resumed) {
2539                // We had hidden the activity because it started another
2540                // one...  we have gotten a result back and we are not
2541                // paused, so make sure our window is visible.
2542                updateVisibility(r, true);
2543            }
2544            if (resumed) {
2545                try {
2546                    // Now we are idle.
2547                    r.activity.mCalled = false;
2548                    mInstrumentation.callActivityOnPause(r.activity);
2549                    if (!r.activity.mCalled) {
2550                        throw new SuperNotCalledException(
2551                            "Activity " + r.intent.getComponent().toShortString()
2552                            + " did not call through to super.onPause()");
2553                    }
2554                } catch (SuperNotCalledException e) {
2555                    throw e;
2556                } catch (Exception e) {
2557                    if (!mInstrumentation.onException(r.activity, e)) {
2558                        throw new RuntimeException(
2559                                "Unable to pause activity "
2560                                + r.intent.getComponent().toShortString()
2561                                + ": " + e.toString(), e);
2562                    }
2563                }
2564            }
2565            deliverResults(r, res.results);
2566            if (resumed) {
2567                mInstrumentation.callActivityOnResume(r.activity);
2568            }
2569        }
2570    }
2571
2572    public final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing) {
2573        return performDestroyActivity(token, finishing, 0, false);
2574    }
2575
2576    private final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
2577            int configChanges, boolean getNonConfigInstance) {
2578        ActivityClientRecord r = mActivities.get(token);
2579        if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
2580        if (r != null) {
2581            r.activity.mConfigChangeFlags |= configChanges;
2582            if (finishing) {
2583                r.activity.mFinished = true;
2584            }
2585            if (getNonConfigInstance) {
2586                r.activity.mChangingConfigurations = true;
2587            }
2588            if (!r.paused) {
2589                try {
2590                    r.activity.mCalled = false;
2591                    mInstrumentation.callActivityOnPause(r.activity);
2592                    EventLog.writeEvent(LOG_ON_PAUSE_CALLED,
2593                            r.activity.getComponentName().getClassName());
2594                    if (!r.activity.mCalled) {
2595                        throw new SuperNotCalledException(
2596                            "Activity " + safeToComponentShortString(r.intent)
2597                            + " did not call through to super.onPause()");
2598                    }
2599                } catch (SuperNotCalledException e) {
2600                    throw e;
2601                } catch (Exception e) {
2602                    if (!mInstrumentation.onException(r.activity, e)) {
2603                        throw new RuntimeException(
2604                                "Unable to pause activity "
2605                                + safeToComponentShortString(r.intent)
2606                                + ": " + e.toString(), e);
2607                    }
2608                }
2609                r.paused = true;
2610            }
2611            if (!r.stopped) {
2612                try {
2613                    r.activity.performStop();
2614                } catch (SuperNotCalledException e) {
2615                    throw e;
2616                } catch (Exception e) {
2617                    if (!mInstrumentation.onException(r.activity, e)) {
2618                        throw new RuntimeException(
2619                                "Unable to stop activity "
2620                                + safeToComponentShortString(r.intent)
2621                                + ": " + e.toString(), e);
2622                    }
2623                }
2624                r.stopped = true;
2625            }
2626            if (getNonConfigInstance) {
2627                try {
2628                    r.lastNonConfigurationInstances
2629                            = r.activity.retainNonConfigurationInstances();
2630                } catch (Exception e) {
2631                    if (!mInstrumentation.onException(r.activity, e)) {
2632                        throw new RuntimeException(
2633                                "Unable to retain activity "
2634                                + r.intent.getComponent().toShortString()
2635                                + ": " + e.toString(), e);
2636                    }
2637                }
2638            }
2639            try {
2640                r.activity.mCalled = false;
2641                mInstrumentation.callActivityOnDestroy(r.activity);
2642                if (!r.activity.mCalled) {
2643                    throw new SuperNotCalledException(
2644                        "Activity " + safeToComponentShortString(r.intent) +
2645                        " did not call through to super.onDestroy()");
2646                }
2647                if (r.window != null) {
2648                    r.window.closeAllPanels();
2649                }
2650            } catch (SuperNotCalledException e) {
2651                throw e;
2652            } catch (Exception e) {
2653                if (!mInstrumentation.onException(r.activity, e)) {
2654                    throw new RuntimeException(
2655                            "Unable to destroy activity " + safeToComponentShortString(r.intent)
2656                            + ": " + e.toString(), e);
2657                }
2658            }
2659        }
2660        mActivities.remove(token);
2661
2662        return r;
2663    }
2664
2665    private static String safeToComponentShortString(Intent intent) {
2666        ComponentName component = intent.getComponent();
2667        return component == null ? "[Unknown]" : component.toShortString();
2668    }
2669
2670    private final void handleDestroyActivity(IBinder token, boolean finishing,
2671            int configChanges, boolean getNonConfigInstance) {
2672        ActivityClientRecord r = performDestroyActivity(token, finishing,
2673                configChanges, getNonConfigInstance);
2674        if (r != null) {
2675            WindowManager wm = r.activity.getWindowManager();
2676            View v = r.activity.mDecor;
2677            if (v != null) {
2678                if (r.activity.mVisibleFromServer) {
2679                    mNumVisibleActivities--;
2680                }
2681                IBinder wtoken = v.getWindowToken();
2682                if (r.activity.mWindowAdded) {
2683                    wm.removeViewImmediate(v);
2684                }
2685                if (wtoken != null) {
2686                    WindowManagerImpl.getDefault().closeAll(wtoken,
2687                            r.activity.getClass().getName(), "Activity");
2688                }
2689                r.activity.mDecor = null;
2690            }
2691            WindowManagerImpl.getDefault().closeAll(token,
2692                    r.activity.getClass().getName(), "Activity");
2693
2694            // Mocked out contexts won't be participating in the normal
2695            // process lifecycle, but if we're running with a proper
2696            // ApplicationContext we need to have it tear down things
2697            // cleanly.
2698            Context c = r.activity.getBaseContext();
2699            if (c instanceof ContextImpl) {
2700                ((ContextImpl) c).scheduleFinalCleanup(
2701                        r.activity.getClass().getName(), "Activity");
2702            }
2703        }
2704        if (finishing) {
2705            try {
2706                ActivityManagerNative.getDefault().activityDestroyed(token);
2707            } catch (RemoteException ex) {
2708                // If the system process has died, it's game over for everyone.
2709            }
2710        }
2711    }
2712
2713    private final void handleRelaunchActivity(ActivityClientRecord tmp, int configChanges) {
2714        // If we are getting ready to gc after going to the background, well
2715        // we are back active so skip it.
2716        unscheduleGcIdler();
2717
2718        Configuration changedConfig = null;
2719
2720        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
2721                + tmp.token + " with configChanges=0x"
2722                + Integer.toHexString(configChanges));
2723
2724        // First: make sure we have the most recent configuration and most
2725        // recent version of the activity, or skip it if some previous call
2726        // had taken a more recent version.
2727        synchronized (mPackages) {
2728            int N = mRelaunchingActivities.size();
2729            IBinder token = tmp.token;
2730            tmp = null;
2731            for (int i=0; i<N; i++) {
2732                ActivityClientRecord r = mRelaunchingActivities.get(i);
2733                if (r.token == token) {
2734                    tmp = r;
2735                    mRelaunchingActivities.remove(i);
2736                    i--;
2737                    N--;
2738                }
2739            }
2740
2741            if (tmp == null) {
2742                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Abort, activity not relaunching!");
2743                return;
2744            }
2745
2746            if (mPendingConfiguration != null) {
2747                changedConfig = mPendingConfiguration;
2748                mPendingConfiguration = null;
2749            }
2750        }
2751
2752        if (tmp.createdConfig != null) {
2753            // If the activity manager is passing us its current config,
2754            // assume that is really what we want regardless of what we
2755            // may have pending.
2756            if (mConfiguration == null
2757                    || (tmp.createdConfig.isOtherSeqNewer(mConfiguration)
2758                            && mConfiguration.diff(tmp.createdConfig) != 0)) {
2759                if (changedConfig == null
2760                        || tmp.createdConfig.isOtherSeqNewer(changedConfig)) {
2761                    changedConfig = tmp.createdConfig;
2762                }
2763            }
2764        }
2765
2766        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
2767                + tmp.token + ": changedConfig=" + changedConfig);
2768
2769        // If there was a pending configuration change, execute it first.
2770        if (changedConfig != null) {
2771            handleConfigurationChanged(changedConfig);
2772        }
2773
2774        ActivityClientRecord r = mActivities.get(tmp.token);
2775        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r);
2776        if (r == null) {
2777            return;
2778        }
2779
2780        r.activity.mConfigChangeFlags |= configChanges;
2781        Intent currentIntent = r.activity.mIntent;
2782
2783        Bundle savedState = null;
2784        if (!r.paused) {
2785            savedState = performPauseActivity(r.token, false, true);
2786        }
2787
2788        handleDestroyActivity(r.token, false, configChanges, true);
2789
2790        r.activity = null;
2791        r.window = null;
2792        r.hideForNow = false;
2793        r.nextIdle = null;
2794        // Merge any pending results and pending intents; don't just replace them
2795        if (tmp.pendingResults != null) {
2796            if (r.pendingResults == null) {
2797                r.pendingResults = tmp.pendingResults;
2798            } else {
2799                r.pendingResults.addAll(tmp.pendingResults);
2800            }
2801        }
2802        if (tmp.pendingIntents != null) {
2803            if (r.pendingIntents == null) {
2804                r.pendingIntents = tmp.pendingIntents;
2805            } else {
2806                r.pendingIntents.addAll(tmp.pendingIntents);
2807            }
2808        }
2809        r.startsNotResumed = tmp.startsNotResumed;
2810        if (savedState != null) {
2811            r.state = savedState;
2812        }
2813
2814        handleLaunchActivity(r, currentIntent);
2815    }
2816
2817    private final void handleRequestThumbnail(IBinder token) {
2818        ActivityClientRecord r = mActivities.get(token);
2819        Bitmap thumbnail = createThumbnailBitmap(r);
2820        CharSequence description = null;
2821        try {
2822            description = r.activity.onCreateDescription();
2823        } catch (Exception e) {
2824            if (!mInstrumentation.onException(r.activity, e)) {
2825                throw new RuntimeException(
2826                        "Unable to create description of activity "
2827                        + r.intent.getComponent().toShortString()
2828                        + ": " + e.toString(), e);
2829            }
2830        }
2831        //System.out.println("Reporting top thumbnail " + thumbnail);
2832        try {
2833            ActivityManagerNative.getDefault().reportThumbnail(
2834                token, thumbnail, description);
2835        } catch (RemoteException ex) {
2836        }
2837    }
2838
2839    ArrayList<ComponentCallbacks> collectComponentCallbacksLocked(
2840            boolean allActivities, Configuration newConfig) {
2841        ArrayList<ComponentCallbacks> callbacks
2842                = new ArrayList<ComponentCallbacks>();
2843
2844        if (mActivities.size() > 0) {
2845            Iterator<ActivityClientRecord> it = mActivities.values().iterator();
2846            while (it.hasNext()) {
2847                ActivityClientRecord ar = it.next();
2848                Activity a = ar.activity;
2849                if (a != null) {
2850                    if (!ar.activity.mFinished && (allActivities ||
2851                            (a != null && !ar.paused))) {
2852                        // If the activity is currently resumed, its configuration
2853                        // needs to change right now.
2854                        callbacks.add(a);
2855                    } else if (newConfig != null) {
2856                        // Otherwise, we will tell it about the change
2857                        // the next time it is resumed or shown.  Note that
2858                        // the activity manager may, before then, decide the
2859                        // activity needs to be destroyed to handle its new
2860                        // configuration.
2861                        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Setting activity "
2862                                + ar.activityInfo.name + " newConfig=" + newConfig);
2863                        ar.newConfig = newConfig;
2864                    }
2865                }
2866            }
2867        }
2868        if (mServices.size() > 0) {
2869            Iterator<Service> it = mServices.values().iterator();
2870            while (it.hasNext()) {
2871                callbacks.add(it.next());
2872            }
2873        }
2874        synchronized (mProviderMap) {
2875            if (mLocalProviders.size() > 0) {
2876                Iterator<ProviderClientRecord> it = mLocalProviders.values().iterator();
2877                while (it.hasNext()) {
2878                    callbacks.add(it.next().mLocalProvider);
2879                }
2880            }
2881        }
2882        final int N = mAllApplications.size();
2883        for (int i=0; i<N; i++) {
2884            callbacks.add(mAllApplications.get(i));
2885        }
2886
2887        return callbacks;
2888    }
2889
2890    private final void performConfigurationChanged(
2891            ComponentCallbacks cb, Configuration config) {
2892        // Only for Activity objects, check that they actually call up to their
2893        // superclass implementation.  ComponentCallbacks is an interface, so
2894        // we check the runtime type and act accordingly.
2895        Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
2896        if (activity != null) {
2897            activity.mCalled = false;
2898        }
2899
2900        boolean shouldChangeConfig = false;
2901        if ((activity == null) || (activity.mCurrentConfig == null)) {
2902            shouldChangeConfig = true;
2903        } else {
2904
2905            // If the new config is the same as the config this Activity
2906            // is already running with then don't bother calling
2907            // onConfigurationChanged
2908            int diff = activity.mCurrentConfig.diff(config);
2909            if (diff != 0) {
2910
2911                // If this activity doesn't handle any of the config changes
2912                // then don't bother calling onConfigurationChanged as we're
2913                // going to destroy it.
2914                if ((~activity.mActivityInfo.configChanges & diff) == 0) {
2915                    shouldChangeConfig = true;
2916                }
2917            }
2918        }
2919
2920        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb
2921                + ": shouldChangeConfig=" + shouldChangeConfig);
2922        if (shouldChangeConfig) {
2923            cb.onConfigurationChanged(config);
2924
2925            if (activity != null) {
2926                if (!activity.mCalled) {
2927                    throw new SuperNotCalledException(
2928                            "Activity " + activity.getLocalClassName() +
2929                        " did not call through to super.onConfigurationChanged()");
2930                }
2931                activity.mConfigChangeFlags = 0;
2932                activity.mCurrentConfig = new Configuration(config);
2933            }
2934        }
2935    }
2936
2937    final boolean applyConfigurationToResourcesLocked(Configuration config) {
2938        if (mResConfiguration == null) {
2939            mResConfiguration = new Configuration();
2940        }
2941        if (!mResConfiguration.isOtherSeqNewer(config)) {
2942            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
2943                    + mResConfiguration.seq + ", newSeq=" + config.seq);
2944            return false;
2945        }
2946        int changes = mResConfiguration.updateFrom(config);
2947        DisplayMetrics dm = getDisplayMetricsLocked(true);
2948
2949        // set it for java, this also affects newly created Resources
2950        if (config.locale != null) {
2951            Locale.setDefault(config.locale);
2952        }
2953
2954        Resources.updateSystemConfiguration(config, dm);
2955
2956        ContextImpl.ApplicationPackageManager.configurationChanged();
2957        //Slog.i(TAG, "Configuration changed in " + currentPackageName());
2958
2959        Iterator<WeakReference<Resources>> it =
2960            mActiveResources.values().iterator();
2961        //Iterator<Map.Entry<String, WeakReference<Resources>>> it =
2962        //    mActiveResources.entrySet().iterator();
2963        while (it.hasNext()) {
2964            WeakReference<Resources> v = it.next();
2965            Resources r = v.get();
2966            if (r != null) {
2967                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
2968                        + r + " config to: " + config);
2969                r.updateConfiguration(config, dm);
2970                //Slog.i(TAG, "Updated app resources " + v.getKey()
2971                //        + " " + r + ": " + r.getConfiguration());
2972            } else {
2973                //Slog.i(TAG, "Removing old resources " + v.getKey());
2974                it.remove();
2975            }
2976        }
2977
2978        return changes != 0;
2979    }
2980
2981    final void handleConfigurationChanged(Configuration config) {
2982
2983        ArrayList<ComponentCallbacks> callbacks = null;
2984
2985        synchronized (mPackages) {
2986            if (mPendingConfiguration != null) {
2987                if (!mPendingConfiguration.isOtherSeqNewer(config)) {
2988                    config = mPendingConfiguration;
2989                }
2990                mPendingConfiguration = null;
2991            }
2992
2993            if (config == null) {
2994                return;
2995            }
2996
2997            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: "
2998                    + config);
2999
3000            applyConfigurationToResourcesLocked(config);
3001
3002            if (mConfiguration == null) {
3003                mConfiguration = new Configuration();
3004            }
3005            if (!mConfiguration.isOtherSeqNewer(config)) {
3006                return;
3007            }
3008            mConfiguration.updateFrom(config);
3009
3010            callbacks = collectComponentCallbacksLocked(false, config);
3011        }
3012
3013        if (callbacks != null) {
3014            final int N = callbacks.size();
3015            for (int i=0; i<N; i++) {
3016                performConfigurationChanged(callbacks.get(i), config);
3017            }
3018        }
3019    }
3020
3021    final void handleActivityConfigurationChanged(IBinder token) {
3022        ActivityClientRecord r = mActivities.get(token);
3023        if (r == null || r.activity == null) {
3024            return;
3025        }
3026
3027        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
3028                + r.activityInfo.name);
3029
3030        performConfigurationChanged(r.activity, mConfiguration);
3031    }
3032
3033    final void handleProfilerControl(boolean start, ProfilerControlData pcd) {
3034        if (start) {
3035            try {
3036                Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(),
3037                        8 * 1024 * 1024, 0);
3038            } catch (RuntimeException e) {
3039                Slog.w(TAG, "Profiling failed on path " + pcd.path
3040                        + " -- can the process access this path?");
3041            } finally {
3042                try {
3043                    pcd.fd.close();
3044                } catch (IOException e) {
3045                    Slog.w(TAG, "Failure closing profile fd", e);
3046                }
3047            }
3048        } else {
3049            Debug.stopMethodTracing();
3050        }
3051    }
3052
3053    final void handleDumpHeap(boolean managed, DumpHeapData dhd) {
3054        if (managed) {
3055            try {
3056                Debug.dumpHprofData(dhd.path, dhd.fd.getFileDescriptor());
3057            } catch (IOException e) {
3058                Slog.w(TAG, "Managed heap dump failed on path " + dhd.path
3059                        + " -- can the process access this path?");
3060            } finally {
3061                try {
3062                    dhd.fd.close();
3063                } catch (IOException e) {
3064                    Slog.w(TAG, "Failure closing profile fd", e);
3065                }
3066            }
3067        } else {
3068            Debug.dumpNativeHeap(dhd.fd.getFileDescriptor());
3069        }
3070    }
3071
3072    final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
3073        boolean hasPkgInfo = false;
3074        if (packages != null) {
3075            for (int i=packages.length-1; i>=0; i--) {
3076                //Slog.i(TAG, "Cleaning old package: " + packages[i]);
3077                if (!hasPkgInfo) {
3078                    WeakReference<LoadedApk> ref;
3079                    ref = mPackages.get(packages[i]);
3080                    if (ref != null && ref.get() != null) {
3081                        hasPkgInfo = true;
3082                    } else {
3083                        ref = mResourcePackages.get(packages[i]);
3084                        if (ref != null && ref.get() != null) {
3085                            hasPkgInfo = true;
3086                        }
3087                    }
3088                }
3089                mPackages.remove(packages[i]);
3090                mResourcePackages.remove(packages[i]);
3091            }
3092        }
3093        ContextImpl.ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
3094                hasPkgInfo);
3095    }
3096
3097    final void handleLowMemory() {
3098        ArrayList<ComponentCallbacks> callbacks
3099                = new ArrayList<ComponentCallbacks>();
3100
3101        synchronized (mPackages) {
3102            callbacks = collectComponentCallbacksLocked(true, null);
3103        }
3104
3105        final int N = callbacks.size();
3106        for (int i=0; i<N; i++) {
3107            callbacks.get(i).onLowMemory();
3108        }
3109
3110        // Ask SQLite to free up as much memory as it can, mostly from its page caches.
3111        if (Process.myUid() != Process.SYSTEM_UID) {
3112            int sqliteReleased = SQLiteDatabase.releaseMemory();
3113            EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
3114        }
3115
3116        // Ask graphics to free up as much as possible (font/image caches)
3117        Canvas.freeCaches();
3118
3119        BinderInternal.forceGc("mem");
3120    }
3121
3122    private final void handleBindApplication(AppBindData data) {
3123        mBoundApplication = data;
3124        mConfiguration = new Configuration(data.config);
3125
3126        // send up app name; do this *before* waiting for debugger
3127        Process.setArgV0(data.processName);
3128        android.ddm.DdmHandleAppName.setAppName(data.processName);
3129
3130        /*
3131         * Before spawning a new process, reset the time zone to be the system time zone.
3132         * This needs to be done because the system time zone could have changed after the
3133         * the spawning of this process. Without doing this this process would have the incorrect
3134         * system time zone.
3135         */
3136        TimeZone.setDefault(null);
3137
3138        /*
3139         * Initialize the default locale in this process for the reasons we set the time zone.
3140         */
3141        Locale.setDefault(data.config.locale);
3142
3143        /*
3144         * Update the system configuration since its preloaded and might not
3145         * reflect configuration changes. The configuration object passed
3146         * in AppBindData can be safely assumed to be up to date
3147         */
3148        Resources.getSystem().updateConfiguration(mConfiguration, null);
3149
3150        data.info = getPackageInfoNoCheck(data.appInfo);
3151
3152        /**
3153         * For system applications on userdebug/eng builds, log stack
3154         * traces of disk and network access to dropbox for analysis.
3155         */
3156        if ((data.appInfo.flags &
3157             (ApplicationInfo.FLAG_SYSTEM |
3158              ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0 &&
3159            !"user".equals(Build.TYPE)) {
3160            StrictMode.setThreadPolicy(
3161                StrictMode.DISALLOW_DISK_WRITE |
3162                StrictMode.DISALLOW_DISK_READ |
3163                StrictMode.DISALLOW_NETWORK |
3164                StrictMode.PENALTY_DROPBOX);
3165        }
3166
3167        /**
3168         * Switch this process to density compatibility mode if needed.
3169         */
3170        if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
3171                == 0) {
3172            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
3173        }
3174
3175        if (data.debugMode != IApplicationThread.DEBUG_OFF) {
3176            // XXX should have option to change the port.
3177            Debug.changeDebugPort(8100);
3178            if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
3179                Slog.w(TAG, "Application " + data.info.getPackageName()
3180                      + " is waiting for the debugger on port 8100...");
3181
3182                IActivityManager mgr = ActivityManagerNative.getDefault();
3183                try {
3184                    mgr.showWaitingForDebugger(mAppThread, true);
3185                } catch (RemoteException ex) {
3186                }
3187
3188                Debug.waitForDebugger();
3189
3190                try {
3191                    mgr.showWaitingForDebugger(mAppThread, false);
3192                } catch (RemoteException ex) {
3193                }
3194
3195            } else {
3196                Slog.w(TAG, "Application " + data.info.getPackageName()
3197                      + " can be debugged on port 8100...");
3198            }
3199        }
3200
3201        if (data.instrumentationName != null) {
3202            ContextImpl appContext = new ContextImpl();
3203            appContext.init(data.info, null, this);
3204            InstrumentationInfo ii = null;
3205            try {
3206                ii = appContext.getPackageManager().
3207                    getInstrumentationInfo(data.instrumentationName, 0);
3208            } catch (PackageManager.NameNotFoundException e) {
3209            }
3210            if (ii == null) {
3211                throw new RuntimeException(
3212                    "Unable to find instrumentation info for: "
3213                    + data.instrumentationName);
3214            }
3215
3216            mInstrumentationAppDir = ii.sourceDir;
3217            mInstrumentationAppPackage = ii.packageName;
3218            mInstrumentedAppDir = data.info.getAppDir();
3219
3220            ApplicationInfo instrApp = new ApplicationInfo();
3221            instrApp.packageName = ii.packageName;
3222            instrApp.sourceDir = ii.sourceDir;
3223            instrApp.publicSourceDir = ii.publicSourceDir;
3224            instrApp.dataDir = ii.dataDir;
3225            instrApp.nativeLibraryDir = ii.nativeLibraryDir;
3226            LoadedApk pi = getPackageInfo(instrApp,
3227                    appContext.getClassLoader(), false, true);
3228            ContextImpl instrContext = new ContextImpl();
3229            instrContext.init(pi, null, this);
3230
3231            try {
3232                java.lang.ClassLoader cl = instrContext.getClassLoader();
3233                mInstrumentation = (Instrumentation)
3234                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
3235            } catch (Exception e) {
3236                throw new RuntimeException(
3237                    "Unable to instantiate instrumentation "
3238                    + data.instrumentationName + ": " + e.toString(), e);
3239            }
3240
3241            mInstrumentation.init(this, instrContext, appContext,
3242                    new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);
3243
3244            if (data.profileFile != null && !ii.handleProfiling) {
3245                data.handlingProfiling = true;
3246                File file = new File(data.profileFile);
3247                file.getParentFile().mkdirs();
3248                Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
3249            }
3250
3251            try {
3252                mInstrumentation.onCreate(data.instrumentationArgs);
3253            }
3254            catch (Exception e) {
3255                throw new RuntimeException(
3256                    "Exception thrown in onCreate() of "
3257                    + data.instrumentationName + ": " + e.toString(), e);
3258            }
3259
3260        } else {
3261            mInstrumentation = new Instrumentation();
3262        }
3263
3264        // If the app is being launched for full backup or restore, bring it up in
3265        // a restricted environment with the base application class.
3266        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
3267        mInitialApplication = app;
3268
3269        List<ProviderInfo> providers = data.providers;
3270        if (providers != null) {
3271            installContentProviders(app, providers);
3272            // For process that contain content providers, we want to
3273            // ensure that the JIT is enabled "at some point".
3274            mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
3275        }
3276
3277        try {
3278            mInstrumentation.callApplicationOnCreate(app);
3279        } catch (Exception e) {
3280            if (!mInstrumentation.onException(app, e)) {
3281                throw new RuntimeException(
3282                    "Unable to create application " + app.getClass().getName()
3283                    + ": " + e.toString(), e);
3284            }
3285        }
3286    }
3287
3288    /*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
3289        IActivityManager am = ActivityManagerNative.getDefault();
3290        if (mBoundApplication.profileFile != null && mBoundApplication.handlingProfiling) {
3291            Debug.stopMethodTracing();
3292        }
3293        //Slog.i(TAG, "am: " + ActivityManagerNative.getDefault()
3294        //      + ", app thr: " + mAppThread);
3295        try {
3296            am.finishInstrumentation(mAppThread, resultCode, results);
3297        } catch (RemoteException ex) {
3298        }
3299    }
3300
3301    private final void installContentProviders(
3302            Context context, List<ProviderInfo> providers) {
3303        final ArrayList<IActivityManager.ContentProviderHolder> results =
3304            new ArrayList<IActivityManager.ContentProviderHolder>();
3305
3306        Iterator<ProviderInfo> i = providers.iterator();
3307        while (i.hasNext()) {
3308            ProviderInfo cpi = i.next();
3309            StringBuilder buf = new StringBuilder(128);
3310            buf.append("Publishing provider ");
3311            buf.append(cpi.authority);
3312            buf.append(": ");
3313            buf.append(cpi.name);
3314            Log.i(TAG, buf.toString());
3315            IContentProvider cp = installProvider(context, null, cpi, false);
3316            if (cp != null) {
3317                IActivityManager.ContentProviderHolder cph =
3318                    new IActivityManager.ContentProviderHolder(cpi);
3319                cph.provider = cp;
3320                results.add(cph);
3321                // Don't ever unload this provider from the process.
3322                synchronized(mProviderMap) {
3323                    mProviderRefCountMap.put(cp.asBinder(), new ProviderRefCount(10000));
3324                }
3325            }
3326        }
3327
3328        try {
3329            ActivityManagerNative.getDefault().publishContentProviders(
3330                getApplicationThread(), results);
3331        } catch (RemoteException ex) {
3332        }
3333    }
3334
3335    private final IContentProvider getProvider(Context context, String name) {
3336        synchronized(mProviderMap) {
3337            final ProviderClientRecord pr = mProviderMap.get(name);
3338            if (pr != null) {
3339                return pr.mProvider;
3340            }
3341        }
3342
3343        IActivityManager.ContentProviderHolder holder = null;
3344        try {
3345            holder = ActivityManagerNative.getDefault().getContentProvider(
3346                getApplicationThread(), name);
3347        } catch (RemoteException ex) {
3348        }
3349        if (holder == null) {
3350            Slog.e(TAG, "Failed to find provider info for " + name);
3351            return null;
3352        }
3353
3354        IContentProvider prov = installProvider(context, holder.provider,
3355                holder.info, true);
3356        //Slog.i(TAG, "noReleaseNeeded=" + holder.noReleaseNeeded);
3357        if (holder.noReleaseNeeded || holder.provider == null) {
3358            // We are not going to release the provider if it is an external
3359            // provider that doesn't care about being released, or if it is
3360            // a local provider running in this process.
3361            //Slog.i(TAG, "*** NO RELEASE NEEDED");
3362            synchronized(mProviderMap) {
3363                mProviderRefCountMap.put(prov.asBinder(), new ProviderRefCount(10000));
3364            }
3365        }
3366        return prov;
3367    }
3368
3369    public final IContentProvider acquireProvider(Context c, String name) {
3370        IContentProvider provider = getProvider(c, name);
3371        if(provider == null)
3372            return null;
3373        IBinder jBinder = provider.asBinder();
3374        synchronized(mProviderMap) {
3375            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
3376            if(prc == null) {
3377                mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
3378            } else {
3379                prc.count++;
3380            } //end else
3381        } //end synchronized
3382        return provider;
3383    }
3384
3385    public final boolean releaseProvider(IContentProvider provider) {
3386        if(provider == null) {
3387            return false;
3388        }
3389        IBinder jBinder = provider.asBinder();
3390        synchronized(mProviderMap) {
3391            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
3392            if(prc == null) {
3393                if(localLOGV) Slog.v(TAG, "releaseProvider::Weird shouldnt be here");
3394                return false;
3395            } else {
3396                prc.count--;
3397                if(prc.count == 0) {
3398                    // Schedule the actual remove asynchronously, since we
3399                    // don't know the context this will be called in.
3400                    // TODO: it would be nice to post a delayed message, so
3401                    // if we come back and need the same provider quickly
3402                    // we will still have it available.
3403                    Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider);
3404                    mH.sendMessage(msg);
3405                } //end if
3406            } //end else
3407        } //end synchronized
3408        return true;
3409    }
3410
3411    final void completeRemoveProvider(IContentProvider provider) {
3412        IBinder jBinder = provider.asBinder();
3413        String name = null;
3414        synchronized(mProviderMap) {
3415            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
3416            if(prc != null && prc.count == 0) {
3417                mProviderRefCountMap.remove(jBinder);
3418                //invoke removeProvider to dereference provider
3419                name = removeProviderLocked(provider);
3420            }
3421        }
3422
3423        if (name != null) {
3424            try {
3425                if(localLOGV) Slog.v(TAG, "removeProvider::Invoking " +
3426                        "ActivityManagerNative.removeContentProvider(" + name);
3427                ActivityManagerNative.getDefault().removeContentProvider(
3428                        getApplicationThread(), name);
3429            } catch (RemoteException e) {
3430                //do nothing content provider object is dead any way
3431            } //end catch
3432        }
3433    }
3434
3435    public final String removeProviderLocked(IContentProvider provider) {
3436        if (provider == null) {
3437            return null;
3438        }
3439        IBinder providerBinder = provider.asBinder();
3440
3441        String name = null;
3442
3443        // remove the provider from mProviderMap
3444        Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator();
3445        while (iter.hasNext()) {
3446            ProviderClientRecord pr = iter.next();
3447            IBinder myBinder = pr.mProvider.asBinder();
3448            if (myBinder == providerBinder) {
3449                //find if its published by this process itself
3450                if(pr.mLocalProvider != null) {
3451                    if(localLOGV) Slog.i(TAG, "removeProvider::found local provider returning");
3452                    return name;
3453                }
3454                if(localLOGV) Slog.v(TAG, "removeProvider::Not local provider Unlinking " +
3455                        "death recipient");
3456                //content provider is in another process
3457                myBinder.unlinkToDeath(pr, 0);
3458                iter.remove();
3459                //invoke remove only once for the very first name seen
3460                if(name == null) {
3461                    name = pr.mName;
3462                }
3463            } //end if myBinder
3464        }  //end while iter
3465
3466        return name;
3467    }
3468
3469    final void removeDeadProvider(String name, IContentProvider provider) {
3470        synchronized(mProviderMap) {
3471            ProviderClientRecord pr = mProviderMap.get(name);
3472            if (pr.mProvider.asBinder() == provider.asBinder()) {
3473                Slog.i(TAG, "Removing dead content provider: " + name);
3474                ProviderClientRecord removed = mProviderMap.remove(name);
3475                if (removed != null) {
3476                    removed.mProvider.asBinder().unlinkToDeath(removed, 0);
3477                }
3478            }
3479        }
3480    }
3481
3482    final void removeDeadProviderLocked(String name, IContentProvider provider) {
3483        ProviderClientRecord pr = mProviderMap.get(name);
3484        if (pr.mProvider.asBinder() == provider.asBinder()) {
3485            Slog.i(TAG, "Removing dead content provider: " + name);
3486            ProviderClientRecord removed = mProviderMap.remove(name);
3487            if (removed != null) {
3488                removed.mProvider.asBinder().unlinkToDeath(removed, 0);
3489            }
3490        }
3491    }
3492
3493    private final IContentProvider installProvider(Context context,
3494            IContentProvider provider, ProviderInfo info, boolean noisy) {
3495        ContentProvider localProvider = null;
3496        if (provider == null) {
3497            if (noisy) {
3498                Slog.d(TAG, "Loading provider " + info.authority + ": "
3499                        + info.name);
3500            }
3501            Context c = null;
3502            ApplicationInfo ai = info.applicationInfo;
3503            if (context.getPackageName().equals(ai.packageName)) {
3504                c = context;
3505            } else if (mInitialApplication != null &&
3506                    mInitialApplication.getPackageName().equals(ai.packageName)) {
3507                c = mInitialApplication;
3508            } else {
3509                try {
3510                    c = context.createPackageContext(ai.packageName,
3511                            Context.CONTEXT_INCLUDE_CODE);
3512                } catch (PackageManager.NameNotFoundException e) {
3513                }
3514            }
3515            if (c == null) {
3516                Slog.w(TAG, "Unable to get context for package " +
3517                      ai.packageName +
3518                      " while loading content provider " +
3519                      info.name);
3520                return null;
3521            }
3522            try {
3523                final java.lang.ClassLoader cl = c.getClassLoader();
3524                localProvider = (ContentProvider)cl.
3525                    loadClass(info.name).newInstance();
3526                provider = localProvider.getIContentProvider();
3527                if (provider == null) {
3528                    Slog.e(TAG, "Failed to instantiate class " +
3529                          info.name + " from sourceDir " +
3530                          info.applicationInfo.sourceDir);
3531                    return null;
3532                }
3533                if (Config.LOGV) Slog.v(
3534                    TAG, "Instantiating local provider " + info.name);
3535                // XXX Need to create the correct context for this provider.
3536                localProvider.attachInfo(c, info);
3537            } catch (java.lang.Exception e) {
3538                if (!mInstrumentation.onException(null, e)) {
3539                    throw new RuntimeException(
3540                            "Unable to get provider " + info.name
3541                            + ": " + e.toString(), e);
3542                }
3543                return null;
3544            }
3545        } else if (localLOGV) {
3546            Slog.v(TAG, "Installing external provider " + info.authority + ": "
3547                    + info.name);
3548        }
3549
3550        synchronized (mProviderMap) {
3551            // Cache the pointer for the remote provider.
3552            String names[] = PATTERN_SEMICOLON.split(info.authority);
3553            for (int i=0; i<names.length; i++) {
3554                ProviderClientRecord pr = new ProviderClientRecord(names[i], provider,
3555                        localProvider);
3556                try {
3557                    provider.asBinder().linkToDeath(pr, 0);
3558                    mProviderMap.put(names[i], pr);
3559                } catch (RemoteException e) {
3560                    return null;
3561                }
3562            }
3563            if (localProvider != null) {
3564                mLocalProviders.put(provider.asBinder(),
3565                        new ProviderClientRecord(null, provider, localProvider));
3566            }
3567        }
3568
3569        return provider;
3570    }
3571
3572    private final void attach(boolean system) {
3573        sThreadLocal.set(this);
3574        mSystemThread = system;
3575        if (!system) {
3576            ViewRoot.addFirstDrawHandler(new Runnable() {
3577                public void run() {
3578                    ensureJitEnabled();
3579                }
3580            });
3581            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
3582            RuntimeInit.setApplicationObject(mAppThread.asBinder());
3583            IActivityManager mgr = ActivityManagerNative.getDefault();
3584            try {
3585                mgr.attachApplication(mAppThread);
3586            } catch (RemoteException ex) {
3587            }
3588        } else {
3589            // Don't set application object here -- if the system crashes,
3590            // we can't display an alert, we just want to die die die.
3591            android.ddm.DdmHandleAppName.setAppName("system_process");
3592            try {
3593                mInstrumentation = new Instrumentation();
3594                ContextImpl context = new ContextImpl();
3595                context.init(getSystemContext().mPackageInfo, null, this);
3596                Application app = Instrumentation.newApplication(Application.class, context);
3597                mAllApplications.add(app);
3598                mInitialApplication = app;
3599                app.onCreate();
3600            } catch (Exception e) {
3601                throw new RuntimeException(
3602                        "Unable to instantiate Application():" + e.toString(), e);
3603            }
3604        }
3605
3606        ViewRoot.addConfigCallback(new ComponentCallbacks() {
3607            public void onConfigurationChanged(Configuration newConfig) {
3608                synchronized (mPackages) {
3609                    // We need to apply this change to the resources
3610                    // immediately, because upon returning the view
3611                    // hierarchy will be informed about it.
3612                    if (applyConfigurationToResourcesLocked(newConfig)) {
3613                        // This actually changed the resources!  Tell
3614                        // everyone about it.
3615                        if (mPendingConfiguration == null ||
3616                                mPendingConfiguration.isOtherSeqNewer(newConfig)) {
3617                            mPendingConfiguration = newConfig;
3618
3619                            queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
3620                        }
3621                    }
3622                }
3623            }
3624            public void onLowMemory() {
3625            }
3626        });
3627    }
3628
3629    private final void detach()
3630    {
3631        sThreadLocal.set(null);
3632    }
3633
3634    public static final ActivityThread systemMain() {
3635        ActivityThread thread = new ActivityThread();
3636        thread.attach(true);
3637        return thread;
3638    }
3639
3640    public final void installSystemProviders(List providers) {
3641        if (providers != null) {
3642            installContentProviders(mInitialApplication,
3643                                    (List<ProviderInfo>)providers);
3644        }
3645    }
3646
3647    public static final void main(String[] args) {
3648        SamplingProfilerIntegration.start();
3649
3650        Process.setArgV0("<pre-initialized>");
3651
3652        Looper.prepareMainLooper();
3653        if (sMainThreadHandler == null) {
3654            sMainThreadHandler = new Handler();
3655        }
3656
3657        ActivityThread thread = new ActivityThread();
3658        thread.attach(false);
3659
3660        Looper.loop();
3661
3662        if (Process.supportsProcesses()) {
3663            throw new RuntimeException("Main thread loop unexpectedly exited");
3664        }
3665
3666        thread.detach();
3667        String name = (thread.mInitialApplication != null)
3668            ? thread.mInitialApplication.getPackageName()
3669            : "<unknown>";
3670        Slog.i(TAG, "Main thread of " + name + " is now exiting");
3671    }
3672}
3673