ActivityThread.java revision 7c5016787ec862445b1d4301787f46d52acfa88d
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.ComponentCallbacks2;
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.net.IConnectivityManager;
46import android.net.Proxy;
47import android.net.ProxyProperties;
48import android.opengl.GLUtils;
49import android.os.AsyncTask;
50import android.os.Binder;
51import android.os.Bundle;
52import android.os.Debug;
53import android.os.Handler;
54import android.os.IBinder;
55import android.os.Looper;
56import android.os.Message;
57import android.os.MessageQueue;
58import android.os.ParcelFileDescriptor;
59import android.os.Process;
60import android.os.RemoteException;
61import android.os.ServiceManager;
62import android.os.StrictMode;
63import android.os.SystemClock;
64import android.os.UserId;
65import android.util.AndroidRuntimeException;
66import android.util.DisplayMetrics;
67import android.util.EventLog;
68import android.util.Log;
69import android.util.LogPrinter;
70import android.util.PrintWriterPrinter;
71import android.util.Slog;
72import android.view.Display;
73import android.view.HardwareRenderer;
74import android.view.View;
75import android.view.ViewDebug;
76import android.view.ViewManager;
77import android.view.ViewRootImpl;
78import android.view.Window;
79import android.view.WindowManager;
80import android.view.WindowManagerImpl;
81import android.renderscript.RenderScript;
82
83import com.android.internal.os.BinderInternal;
84import com.android.internal.os.RuntimeInit;
85import com.android.internal.os.SamplingProfilerIntegration;
86
87import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
88
89import java.io.File;
90import java.io.FileDescriptor;
91import java.io.FileOutputStream;
92import java.io.IOException;
93import java.io.PrintWriter;
94import java.lang.ref.WeakReference;
95import java.net.InetAddress;
96import java.util.ArrayList;
97import java.util.HashMap;
98import java.util.Iterator;
99import java.util.List;
100import java.util.Locale;
101import java.util.Map;
102import java.util.TimeZone;
103import java.util.regex.Pattern;
104
105import dalvik.system.CloseGuard;
106
107final class SuperNotCalledException extends AndroidRuntimeException {
108    public SuperNotCalledException(String msg) {
109        super(msg);
110    }
111}
112
113final class RemoteServiceException extends AndroidRuntimeException {
114    public RemoteServiceException(String msg) {
115        super(msg);
116    }
117}
118
119/**
120 * This manages the execution of the main thread in an
121 * application process, scheduling and executing activities,
122 * broadcasts, and other operations on it as the activity
123 * manager requests.
124 *
125 * {@hide}
126 */
127public final class ActivityThread {
128    /** @hide */
129    public static final String TAG = "ActivityThread";
130    private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
131    static final boolean localLOGV = false;
132    static final boolean DEBUG_MESSAGES = false;
133    /** @hide */
134    public static final boolean DEBUG_BROADCAST = false;
135    private static final boolean DEBUG_RESULTS = false;
136    private static final boolean DEBUG_BACKUP = true;
137    private static final boolean DEBUG_CONFIGURATION = false;
138    private static final boolean DEBUG_SERVICE = false;
139    private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
140    private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";");
141    private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
142    private static final int LOG_ON_PAUSE_CALLED = 30021;
143    private static final int LOG_ON_RESUME_CALLED = 30022;
144
145    static ContextImpl mSystemContext = null;
146
147    static IPackageManager sPackageManager;
148
149    final ApplicationThread mAppThread = new ApplicationThread();
150    final Looper mLooper = Looper.myLooper();
151    final H mH = new H();
152    final HashMap<IBinder, ActivityClientRecord> mActivities
153            = new HashMap<IBinder, ActivityClientRecord>();
154    // List of new activities (via ActivityRecord.nextIdle) that should
155    // be reported when next we idle.
156    ActivityClientRecord mNewActivities = null;
157    // Number of activities that are currently visible on-screen.
158    int mNumVisibleActivities = 0;
159    final HashMap<IBinder, Service> mServices
160            = new HashMap<IBinder, Service>();
161    AppBindData mBoundApplication;
162    Profiler mProfiler;
163    Configuration mConfiguration;
164    Configuration mCompatConfiguration;
165    Configuration mResConfiguration;
166    CompatibilityInfo mResCompatibilityInfo;
167    Application mInitialApplication;
168    final ArrayList<Application> mAllApplications
169            = new ArrayList<Application>();
170    // set of instantiated backup agents, keyed by package name
171    final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>();
172    static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal<ActivityThread>();
173    Instrumentation mInstrumentation;
174    String mInstrumentationAppDir = null;
175    String mInstrumentationAppPackage = null;
176    String mInstrumentedAppDir = null;
177    boolean mSystemThread = false;
178    boolean mJitEnabled = false;
179
180    // These can be accessed by multiple threads; mPackages is the lock.
181    // XXX For now we keep around information about all packages we have
182    // seen, not removing entries from this map.
183    // NOTE: The activity and window managers need to call in to
184    // ActivityThread to do things like update resource configurations,
185    // which means this lock gets held while the activity and window managers
186    // holds their own lock.  Thus you MUST NEVER call back into the activity manager
187    // or window manager or anything that depends on them while holding this lock.
188    final HashMap<String, WeakReference<LoadedApk>> mPackages
189            = new HashMap<String, WeakReference<LoadedApk>>();
190    final HashMap<String, WeakReference<LoadedApk>> mResourcePackages
191            = new HashMap<String, WeakReference<LoadedApk>>();
192    final HashMap<CompatibilityInfo, DisplayMetrics> mDisplayMetrics
193            = new HashMap<CompatibilityInfo, DisplayMetrics>();
194    final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
195            = new HashMap<ResourcesKey, WeakReference<Resources> >();
196    final ArrayList<ActivityClientRecord> mRelaunchingActivities
197            = new ArrayList<ActivityClientRecord>();
198    Configuration mPendingConfiguration = null;
199
200    // The lock of mProviderMap protects the following variables.
201    final HashMap<String, ProviderClientRecord> mProviderMap
202        = new HashMap<String, ProviderClientRecord>();
203    final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap
204        = new HashMap<IBinder, ProviderRefCount>();
205    final HashMap<IBinder, ProviderClientRecord> mLocalProviders
206        = new HashMap<IBinder, ProviderClientRecord>();
207
208    final HashMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners
209        = new HashMap<Activity, ArrayList<OnActivityPausedListener>>();
210
211    final GcIdler mGcIdler = new GcIdler();
212    boolean mGcIdlerScheduled = false;
213
214    static Handler sMainThreadHandler;  // set once in main()
215
216    Bundle mCoreSettings = null;
217
218    static final class ActivityClientRecord {
219        IBinder token;
220        int ident;
221        Intent intent;
222        Bundle state;
223        Activity activity;
224        Window window;
225        Activity parent;
226        String embeddedID;
227        Activity.NonConfigurationInstances lastNonConfigurationInstances;
228        boolean paused;
229        boolean stopped;
230        boolean hideForNow;
231        Configuration newConfig;
232        Configuration createdConfig;
233        ActivityClientRecord nextIdle;
234
235        String profileFile;
236        ParcelFileDescriptor profileFd;
237        boolean autoStopProfiler;
238
239        ActivityInfo activityInfo;
240        CompatibilityInfo compatInfo;
241        LoadedApk packageInfo;
242
243        List<ResultInfo> pendingResults;
244        List<Intent> pendingIntents;
245
246        boolean startsNotResumed;
247        boolean isForward;
248        int pendingConfigChanges;
249        boolean onlyLocalRequest;
250
251        View mPendingRemoveWindow;
252        WindowManager mPendingRemoveWindowManager;
253
254        ActivityClientRecord() {
255            parent = null;
256            embeddedID = null;
257            paused = false;
258            stopped = false;
259            hideForNow = false;
260            nextIdle = null;
261        }
262
263        public boolean isPreHoneycomb() {
264            if (activity != null) {
265                return activity.getApplicationInfo().targetSdkVersion
266                        < android.os.Build.VERSION_CODES.HONEYCOMB;
267            }
268            return false;
269        }
270
271        public String toString() {
272            ComponentName componentName = intent.getComponent();
273            return "ActivityRecord{"
274                + Integer.toHexString(System.identityHashCode(this))
275                + " token=" + token + " " + (componentName == null
276                        ? "no component name" : componentName.toShortString())
277                + "}";
278        }
279    }
280
281    final class ProviderClientRecord implements IBinder.DeathRecipient {
282        final String mName;
283        final IContentProvider mProvider;
284        final ContentProvider mLocalProvider;
285
286        ProviderClientRecord(String name, IContentProvider provider,
287                ContentProvider localProvider) {
288            mName = name;
289            mProvider = provider;
290            mLocalProvider = localProvider;
291        }
292
293        public void binderDied() {
294            removeDeadProvider(mName, mProvider);
295        }
296    }
297
298    static final class NewIntentData {
299        List<Intent> intents;
300        IBinder token;
301        public String toString() {
302            return "NewIntentData{intents=" + intents + " token=" + token + "}";
303        }
304    }
305
306    static final class ReceiverData extends BroadcastReceiver.PendingResult {
307        public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras,
308                boolean ordered, boolean sticky, IBinder token) {
309            super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky, token);
310            this.intent = intent;
311        }
312
313        Intent intent;
314        ActivityInfo info;
315        CompatibilityInfo compatInfo;
316        public String toString() {
317            return "ReceiverData{intent=" + intent + " packageName=" +
318                    info.packageName + " resultCode=" + getResultCode()
319                    + " resultData=" + getResultData() + " resultExtras="
320                    + getResultExtras(false) + "}";
321        }
322    }
323
324    static final class CreateBackupAgentData {
325        ApplicationInfo appInfo;
326        CompatibilityInfo compatInfo;
327        int backupMode;
328        public String toString() {
329            return "CreateBackupAgentData{appInfo=" + appInfo
330                    + " backupAgent=" + appInfo.backupAgentName
331                    + " mode=" + backupMode + "}";
332        }
333    }
334
335    static final class CreateServiceData {
336        IBinder token;
337        ServiceInfo info;
338        CompatibilityInfo compatInfo;
339        Intent intent;
340        public String toString() {
341            return "CreateServiceData{token=" + token + " className="
342            + info.name + " packageName=" + info.packageName
343            + " intent=" + intent + "}";
344        }
345    }
346
347    static final class BindServiceData {
348        IBinder token;
349        Intent intent;
350        boolean rebind;
351        public String toString() {
352            return "BindServiceData{token=" + token + " intent=" + intent + "}";
353        }
354    }
355
356    static final class ServiceArgsData {
357        IBinder token;
358        boolean taskRemoved;
359        int startId;
360        int flags;
361        Intent args;
362        public String toString() {
363            return "ServiceArgsData{token=" + token + " startId=" + startId
364            + " args=" + args + "}";
365        }
366    }
367
368    static final class AppBindData {
369        LoadedApk info;
370        String processName;
371        ApplicationInfo appInfo;
372        List<ProviderInfo> providers;
373        ComponentName instrumentationName;
374        Bundle instrumentationArgs;
375        IInstrumentationWatcher instrumentationWatcher;
376        int debugMode;
377        boolean restrictedBackupMode;
378        boolean persistent;
379        Configuration config;
380        CompatibilityInfo compatInfo;
381
382        /** Initial values for {@link Profiler}. */
383        String initProfileFile;
384        ParcelFileDescriptor initProfileFd;
385        boolean initAutoStopProfiler;
386
387        public String toString() {
388            return "AppBindData{appInfo=" + appInfo + "}";
389        }
390    }
391
392    static final class Profiler {
393        String profileFile;
394        ParcelFileDescriptor profileFd;
395        boolean autoStopProfiler;
396        boolean profiling;
397        boolean handlingProfiling;
398        public void setProfiler(String file, ParcelFileDescriptor fd) {
399            if (profiling) {
400                if (fd != null) {
401                    try {
402                        fd.close();
403                    } catch (IOException e) {
404                    }
405                }
406                return;
407            }
408            if (profileFd != null) {
409                try {
410                    profileFd.close();
411                } catch (IOException e) {
412                }
413            }
414            profileFile = file;
415            profileFd = fd;
416        }
417        public void startProfiling() {
418            if (profileFd == null || profiling) {
419                return;
420            }
421            try {
422                Debug.startMethodTracing(profileFile, profileFd.getFileDescriptor(),
423                        8 * 1024 * 1024, 0);
424                profiling = true;
425            } catch (RuntimeException e) {
426                Slog.w(TAG, "Profiling failed on path " + profileFile);
427                try {
428                    profileFd.close();
429                    profileFd = null;
430                } catch (IOException e2) {
431                    Slog.w(TAG, "Failure closing profile fd", e2);
432                }
433            }
434        }
435        public void stopProfiling() {
436            if (profiling) {
437                profiling = false;
438                Debug.stopMethodTracing();
439                if (profileFd != null) {
440                    try {
441                        profileFd.close();
442                    } catch (IOException e) {
443                    }
444                }
445                profileFd = null;
446                profileFile = null;
447            }
448        }
449    }
450
451    static final class DumpComponentInfo {
452        ParcelFileDescriptor fd;
453        IBinder token;
454        String prefix;
455        String[] args;
456    }
457
458    static final class ResultData {
459        IBinder token;
460        List<ResultInfo> results;
461        public String toString() {
462            return "ResultData{token=" + token + " results" + results + "}";
463        }
464    }
465
466    static final class ContextCleanupInfo {
467        ContextImpl context;
468        String what;
469        String who;
470    }
471
472    static final class ProfilerControlData {
473        String path;
474        ParcelFileDescriptor fd;
475    }
476
477    static final class DumpHeapData {
478        String path;
479        ParcelFileDescriptor fd;
480    }
481
482    static final class UpdateCompatibilityData {
483        String pkg;
484        CompatibilityInfo info;
485    }
486
487    private native void dumpGraphicsInfo(FileDescriptor fd);
488
489    private class ApplicationThread extends ApplicationThreadNative {
490        private static final String HEAP_COLUMN = "%13s %8s %8s %8s %8s %8s %8s";
491        private static final String ONE_COUNT_COLUMN = "%21s %8d";
492        private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d";
493        private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";
494
495        // Formatting for checkin service - update version if row format changes
496        private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1;
497
498        private void updatePendingConfiguration(Configuration config) {
499            synchronized (mPackages) {
500                if (mPendingConfiguration == null ||
501                        mPendingConfiguration.isOtherSeqNewer(config)) {
502                    mPendingConfiguration = config;
503                }
504            }
505        }
506
507        public final void schedulePauseActivity(IBinder token, boolean finished,
508                boolean userLeaving, int configChanges) {
509            queueOrSendMessage(
510                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
511                    token,
512                    (userLeaving ? 1 : 0),
513                    configChanges);
514        }
515
516        public final void scheduleStopActivity(IBinder token, boolean showWindow,
517                int configChanges) {
518           queueOrSendMessage(
519                showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
520                token, 0, configChanges);
521        }
522
523        public final void scheduleWindowVisibility(IBinder token, boolean showWindow) {
524            queueOrSendMessage(
525                showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW,
526                token);
527        }
528
529        public final void scheduleSleeping(IBinder token, boolean sleeping) {
530            queueOrSendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
531        }
532
533        public final void scheduleResumeActivity(IBinder token, boolean isForward) {
534            queueOrSendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
535        }
536
537        public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
538            ResultData res = new ResultData();
539            res.token = token;
540            res.results = results;
541            queueOrSendMessage(H.SEND_RESULT, res);
542        }
543
544        // we use token to identify this activity without having to send the
545        // activity itself back to the activity manager. (matters more with ipc)
546        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
547                ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
548                Bundle state, List<ResultInfo> pendingResults,
549                List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
550                String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
551            ActivityClientRecord r = new ActivityClientRecord();
552
553            r.token = token;
554            r.ident = ident;
555            r.intent = intent;
556            r.activityInfo = info;
557            r.compatInfo = compatInfo;
558            r.state = state;
559
560            r.pendingResults = pendingResults;
561            r.pendingIntents = pendingNewIntents;
562
563            r.startsNotResumed = notResumed;
564            r.isForward = isForward;
565
566            r.profileFile = profileName;
567            r.profileFd = profileFd;
568            r.autoStopProfiler = autoStopProfiler;
569
570            updatePendingConfiguration(curConfig);
571
572            queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
573        }
574
575        public final void scheduleRelaunchActivity(IBinder token,
576                List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
577                int configChanges, boolean notResumed, Configuration config) {
578            requestRelaunchActivity(token, pendingResults, pendingNewIntents,
579                    configChanges, notResumed, config, true);
580        }
581
582        public final void scheduleNewIntent(List<Intent> intents, IBinder token) {
583            NewIntentData data = new NewIntentData();
584            data.intents = intents;
585            data.token = token;
586
587            queueOrSendMessage(H.NEW_INTENT, data);
588        }
589
590        public final void scheduleDestroyActivity(IBinder token, boolean finishing,
591                int configChanges) {
592            queueOrSendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
593                    configChanges);
594        }
595
596        public final void scheduleReceiver(Intent intent, ActivityInfo info,
597                CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
598                boolean sync) {
599            ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
600                    sync, false, mAppThread.asBinder());
601            r.info = info;
602            r.compatInfo = compatInfo;
603            queueOrSendMessage(H.RECEIVER, r);
604        }
605
606        public final void scheduleCreateBackupAgent(ApplicationInfo app,
607                CompatibilityInfo compatInfo, int backupMode) {
608            CreateBackupAgentData d = new CreateBackupAgentData();
609            d.appInfo = app;
610            d.compatInfo = compatInfo;
611            d.backupMode = backupMode;
612
613            queueOrSendMessage(H.CREATE_BACKUP_AGENT, d);
614        }
615
616        public final void scheduleDestroyBackupAgent(ApplicationInfo app,
617                CompatibilityInfo compatInfo) {
618            CreateBackupAgentData d = new CreateBackupAgentData();
619            d.appInfo = app;
620            d.compatInfo = compatInfo;
621
622            queueOrSendMessage(H.DESTROY_BACKUP_AGENT, d);
623        }
624
625        public final void scheduleCreateService(IBinder token,
626                ServiceInfo info, CompatibilityInfo compatInfo) {
627            CreateServiceData s = new CreateServiceData();
628            s.token = token;
629            s.info = info;
630            s.compatInfo = compatInfo;
631
632            queueOrSendMessage(H.CREATE_SERVICE, s);
633        }
634
635        public final void scheduleBindService(IBinder token, Intent intent,
636                boolean rebind) {
637            BindServiceData s = new BindServiceData();
638            s.token = token;
639            s.intent = intent;
640            s.rebind = rebind;
641
642            if (DEBUG_SERVICE)
643                Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
644                        + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
645            queueOrSendMessage(H.BIND_SERVICE, s);
646        }
647
648        public final void scheduleUnbindService(IBinder token, Intent intent) {
649            BindServiceData s = new BindServiceData();
650            s.token = token;
651            s.intent = intent;
652
653            queueOrSendMessage(H.UNBIND_SERVICE, s);
654        }
655
656        public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
657            int flags ,Intent args) {
658            ServiceArgsData s = new ServiceArgsData();
659            s.token = token;
660            s.taskRemoved = taskRemoved;
661            s.startId = startId;
662            s.flags = flags;
663            s.args = args;
664
665            queueOrSendMessage(H.SERVICE_ARGS, s);
666        }
667
668        public final void scheduleStopService(IBinder token) {
669            queueOrSendMessage(H.STOP_SERVICE, token);
670        }
671
672        public final void bindApplication(String processName,
673                ApplicationInfo appInfo, List<ProviderInfo> providers,
674                ComponentName instrumentationName, String profileFile,
675                ParcelFileDescriptor profileFd, boolean autoStopProfiler,
676                Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
677                int debugMode, boolean isRestrictedBackupMode, boolean persistent,
678                Configuration config, CompatibilityInfo compatInfo,
679                Map<String, IBinder> services, Bundle coreSettings) {
680
681            if (services != null) {
682                // Setup the service cache in the ServiceManager
683                ServiceManager.initServiceCache(services);
684            }
685
686            setCoreSettings(coreSettings);
687
688            AppBindData data = new AppBindData();
689            data.processName = processName;
690            data.appInfo = appInfo;
691            data.providers = providers;
692            data.instrumentationName = instrumentationName;
693            data.instrumentationArgs = instrumentationArgs;
694            data.instrumentationWatcher = instrumentationWatcher;
695            data.debugMode = debugMode;
696            data.restrictedBackupMode = isRestrictedBackupMode;
697            data.persistent = persistent;
698            data.config = config;
699            data.compatInfo = compatInfo;
700            data.initProfileFile = profileFile;
701            data.initProfileFd = profileFd;
702            data.initAutoStopProfiler = false;
703            queueOrSendMessage(H.BIND_APPLICATION, data);
704        }
705
706        public final void scheduleExit() {
707            queueOrSendMessage(H.EXIT_APPLICATION, null);
708        }
709
710        public final void scheduleSuicide() {
711            queueOrSendMessage(H.SUICIDE, null);
712        }
713
714        public void requestThumbnail(IBinder token) {
715            queueOrSendMessage(H.REQUEST_THUMBNAIL, token);
716        }
717
718        public void scheduleConfigurationChanged(Configuration config) {
719            updatePendingConfiguration(config);
720            queueOrSendMessage(H.CONFIGURATION_CHANGED, config);
721        }
722
723        public void updateTimeZone() {
724            TimeZone.setDefault(null);
725        }
726
727        public void clearDnsCache() {
728            // a non-standard API to get this to libcore
729            InetAddress.clearDnsCache();
730        }
731
732        public void setHttpProxy(String host, String port, String exclList) {
733            Proxy.setHttpProxySystemProperty(host, port, exclList);
734        }
735
736        public void processInBackground() {
737            mH.removeMessages(H.GC_WHEN_IDLE);
738            mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
739        }
740
741        public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) {
742            DumpComponentInfo data = new DumpComponentInfo();
743            try {
744                data.fd = ParcelFileDescriptor.dup(fd);
745                data.token = servicetoken;
746                data.args = args;
747                queueOrSendMessage(H.DUMP_SERVICE, data);
748            } catch (IOException e) {
749                Slog.w(TAG, "dumpService failed", e);
750            }
751        }
752
753        // This function exists to make sure all receiver dispatching is
754        // correctly ordered, since these are one-way calls and the binder driver
755        // applies transaction ordering per object for such calls.
756        public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
757                int resultCode, String dataStr, Bundle extras, boolean ordered,
758                boolean sticky) throws RemoteException {
759            receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky);
760        }
761
762        public void scheduleLowMemory() {
763            queueOrSendMessage(H.LOW_MEMORY, null);
764        }
765
766        public void scheduleActivityConfigurationChanged(IBinder token) {
767            queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED, token);
768        }
769
770        public void profilerControl(boolean start, String path, ParcelFileDescriptor fd,
771                int profileType) {
772            ProfilerControlData pcd = new ProfilerControlData();
773            pcd.path = path;
774            pcd.fd = fd;
775            queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0, profileType);
776        }
777
778        public void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) {
779            DumpHeapData dhd = new DumpHeapData();
780            dhd.path = path;
781            dhd.fd = fd;
782            queueOrSendMessage(H.DUMP_HEAP, dhd, managed ? 1 : 0);
783        }
784
785        public void setSchedulingGroup(int group) {
786            // Note: do this immediately, since going into the foreground
787            // should happen regardless of what pending work we have to do
788            // and the activity manager will wait for us to report back that
789            // we are done before sending us to the background.
790            try {
791                Process.setProcessGroup(Process.myPid(), group);
792            } catch (Exception e) {
793                Slog.w(TAG, "Failed setting process group to " + group, e);
794            }
795        }
796
797        public void getMemoryInfo(Debug.MemoryInfo outInfo) {
798            Debug.getMemoryInfo(outInfo);
799        }
800
801        public void dispatchPackageBroadcast(int cmd, String[] packages) {
802            queueOrSendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
803        }
804
805        public void scheduleCrash(String msg) {
806            queueOrSendMessage(H.SCHEDULE_CRASH, msg);
807        }
808
809        public void dumpActivity(FileDescriptor fd, IBinder activitytoken,
810                String prefix, String[] args) {
811            DumpComponentInfo data = new DumpComponentInfo();
812            try {
813                data.fd = ParcelFileDescriptor.dup(fd);
814                data.token = activitytoken;
815                data.prefix = prefix;
816                data.args = args;
817                queueOrSendMessage(H.DUMP_ACTIVITY, data);
818            } catch (IOException e) {
819                Slog.w(TAG, "dumpActivity failed", e);
820            }
821        }
822
823        public void dumpProvider(FileDescriptor fd, IBinder providertoken,
824                String[] args) {
825            DumpComponentInfo data = new DumpComponentInfo();
826            try {
827                data.fd = ParcelFileDescriptor.dup(fd);
828                data.token = providertoken;
829                data.args = args;
830                queueOrSendMessage(H.DUMP_PROVIDER, data);
831            } catch (IOException e) {
832                Slog.w(TAG, "dumpProvider failed", e);
833            }
834        }
835
836        @Override
837        public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, boolean checkin,
838                boolean all, String[] args) {
839            FileOutputStream fout = new FileOutputStream(fd);
840            PrintWriter pw = new PrintWriter(fout);
841            try {
842                return dumpMemInfo(pw, checkin, all, args);
843            } finally {
844                pw.flush();
845            }
846        }
847
848        private Debug.MemoryInfo dumpMemInfo(PrintWriter pw, boolean checkin, boolean all,
849                String[] args) {
850            long nativeMax = Debug.getNativeHeapSize() / 1024;
851            long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
852            long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
853
854            Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
855            Debug.getMemoryInfo(memInfo);
856
857            if (!all) {
858                return memInfo;
859            }
860
861            Runtime runtime = Runtime.getRuntime();
862
863            long dalvikMax = runtime.totalMemory() / 1024;
864            long dalvikFree = runtime.freeMemory() / 1024;
865            long dalvikAllocated = dalvikMax - dalvikFree;
866            long viewInstanceCount = ViewDebug.getViewInstanceCount();
867            long viewRootInstanceCount = ViewDebug.getViewRootImplCount();
868            long appContextInstanceCount = Debug.countInstancesOfClass(ContextImpl.class);
869            long activityInstanceCount = Debug.countInstancesOfClass(Activity.class);
870            int globalAssetCount = AssetManager.getGlobalAssetCount();
871            int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
872            int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
873            int binderProxyObjectCount = Debug.getBinderProxyObjectCount();
874            int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
875            long openSslSocketCount = Debug.countInstancesOfClass(OpenSSLSocketImpl.class);
876            SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo();
877
878            // For checkin, we print one long comma-separated list of values
879            if (checkin) {
880                // NOTE: if you change anything significant below, also consider changing
881                // ACTIVITY_THREAD_CHECKIN_VERSION.
882                String processName = (mBoundApplication != null)
883                        ? mBoundApplication.processName : "unknown";
884
885                // Header
886                pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(',');
887                pw.print(Process.myPid()); pw.print(',');
888                pw.print(processName); pw.print(',');
889
890                // Heap info - max
891                pw.print(nativeMax); pw.print(',');
892                pw.print(dalvikMax); pw.print(',');
893                pw.print("N/A,");
894                pw.print(nativeMax + dalvikMax); pw.print(',');
895
896                // Heap info - allocated
897                pw.print(nativeAllocated); pw.print(',');
898                pw.print(dalvikAllocated); pw.print(',');
899                pw.print("N/A,");
900                pw.print(nativeAllocated + dalvikAllocated); pw.print(',');
901
902                // Heap info - free
903                pw.print(nativeFree); pw.print(',');
904                pw.print(dalvikFree); pw.print(',');
905                pw.print("N/A,");
906                pw.print(nativeFree + dalvikFree); pw.print(',');
907
908                // Heap info - proportional set size
909                pw.print(memInfo.nativePss); pw.print(',');
910                pw.print(memInfo.dalvikPss); pw.print(',');
911                pw.print(memInfo.otherPss); pw.print(',');
912                pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(',');
913
914                // Heap info - shared
915                pw.print(memInfo.nativeSharedDirty); pw.print(',');
916                pw.print(memInfo.dalvikSharedDirty); pw.print(',');
917                pw.print(memInfo.otherSharedDirty); pw.print(',');
918                pw.print(memInfo.nativeSharedDirty + memInfo.dalvikSharedDirty
919                        + memInfo.otherSharedDirty); pw.print(',');
920
921                // Heap info - private
922                pw.print(memInfo.nativePrivateDirty); pw.print(',');
923                pw.print(memInfo.dalvikPrivateDirty); pw.print(',');
924                pw.print(memInfo.otherPrivateDirty); pw.print(',');
925                pw.print(memInfo.nativePrivateDirty + memInfo.dalvikPrivateDirty
926                        + memInfo.otherPrivateDirty); pw.print(',');
927
928                // Object counts
929                pw.print(viewInstanceCount); pw.print(',');
930                pw.print(viewRootInstanceCount); pw.print(',');
931                pw.print(appContextInstanceCount); pw.print(',');
932                pw.print(activityInstanceCount); pw.print(',');
933
934                pw.print(globalAssetCount); pw.print(',');
935                pw.print(globalAssetManagerCount); pw.print(',');
936                pw.print(binderLocalObjectCount); pw.print(',');
937                pw.print(binderProxyObjectCount); pw.print(',');
938
939                pw.print(binderDeathObjectCount); pw.print(',');
940                pw.print(openSslSocketCount); pw.print(',');
941
942                // SQL
943                pw.print(stats.memoryUsed / 1024); pw.print(',');
944                pw.print(stats.memoryUsed / 1024); pw.print(',');
945                pw.print(stats.pageCacheOverflow / 1024); pw.print(',');
946                pw.print(stats.largestMemAlloc / 1024);
947                for (int i = 0; i < stats.dbStats.size(); i++) {
948                    DbStats dbStats = stats.dbStats.get(i);
949                    pw.print(','); pw.print(dbStats.dbName);
950                    pw.print(','); pw.print(dbStats.pageSize);
951                    pw.print(','); pw.print(dbStats.dbSize);
952                    pw.print(','); pw.print(dbStats.lookaside);
953                    pw.print(','); pw.print(dbStats.cache);
954                    pw.print(','); pw.print(dbStats.cache);
955                }
956                pw.println();
957
958                return memInfo;
959            }
960
961            // otherwise, show human-readable format
962            printRow(pw, HEAP_COLUMN, "", "", "Shared", "Private", "Heap", "Heap", "Heap");
963            printRow(pw, HEAP_COLUMN, "", "Pss", "Dirty", "Dirty", "Size", "Alloc", "Free");
964            printRow(pw, HEAP_COLUMN, "", "------", "------", "------", "------", "------",
965                    "------");
966            printRow(pw, HEAP_COLUMN, "Native", memInfo.nativePss, memInfo.nativeSharedDirty,
967                    memInfo.nativePrivateDirty, nativeMax, nativeAllocated, nativeFree);
968            printRow(pw, HEAP_COLUMN, "Dalvik", memInfo.dalvikPss, memInfo.dalvikSharedDirty,
969                    memInfo.dalvikPrivateDirty, dalvikMax, dalvikAllocated, dalvikFree);
970
971            int otherPss = memInfo.otherPss;
972            int otherSharedDirty = memInfo.otherSharedDirty;
973            int otherPrivateDirty = memInfo.otherPrivateDirty;
974
975            for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
976                printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
977                        memInfo.getOtherPss(i), memInfo.getOtherSharedDirty(i),
978                        memInfo.getOtherPrivateDirty(i), "", "", "");
979                otherPss -= memInfo.getOtherPss(i);
980                otherSharedDirty -= memInfo.getOtherSharedDirty(i);
981                otherPrivateDirty -= memInfo.getOtherPrivateDirty(i);
982            }
983
984            printRow(pw, HEAP_COLUMN, "Unknown", otherPss, otherSharedDirty,
985                    otherPrivateDirty, "", "", "");
986            printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(),
987                    memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
988                    nativeMax+dalvikMax, nativeAllocated+dalvikAllocated,
989                    nativeFree+dalvikFree);
990
991            pw.println(" ");
992            pw.println(" Objects");
993            printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRootImpl:",
994                    viewRootInstanceCount);
995
996            printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount,
997                    "Activities:", activityInstanceCount);
998
999            printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount,
1000                    "AssetManagers:", globalAssetManagerCount);
1001
1002            printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount,
1003                    "Proxy Binders:", binderProxyObjectCount);
1004            printRow(pw, ONE_COUNT_COLUMN, "Death Recipients:", binderDeathObjectCount);
1005
1006            printRow(pw, ONE_COUNT_COLUMN, "OpenSSL Sockets:", openSslSocketCount);
1007
1008            // SQLite mem info
1009            pw.println(" ");
1010            pw.println(" SQL");
1011            printRow(pw, ONE_COUNT_COLUMN, "MEMORY_USED:", stats.memoryUsed / 1024);
1012            printRow(pw, TWO_COUNT_COLUMNS, "PAGECACHE_OVERFLOW:",
1013                    stats.pageCacheOverflow / 1024, "MALLOC_SIZE:", stats.largestMemAlloc / 1024);
1014            pw.println(" ");
1015            int N = stats.dbStats.size();
1016            if (N > 0) {
1017                pw.println(" DATABASES");
1018                printRow(pw, "  %8s %8s %14s %14s  %s", "pgsz", "dbsz", "Lookaside(b)", "cache",
1019                        "Dbname");
1020                for (int i = 0; i < N; i++) {
1021                    DbStats dbStats = stats.dbStats.get(i);
1022                    printRow(pw, DB_INFO_FORMAT,
1023                            (dbStats.pageSize > 0) ? String.valueOf(dbStats.pageSize) : " ",
1024                            (dbStats.dbSize > 0) ? String.valueOf(dbStats.dbSize) : " ",
1025                            (dbStats.lookaside > 0) ? String.valueOf(dbStats.lookaside) : " ",
1026                            dbStats.cache, dbStats.dbName);
1027                }
1028            }
1029
1030            // Asset details.
1031            String assetAlloc = AssetManager.getAssetAllocations();
1032            if (assetAlloc != null) {
1033                pw.println(" ");
1034                pw.println(" Asset Allocations");
1035                pw.print(assetAlloc);
1036            }
1037
1038            return memInfo;
1039        }
1040
1041        @Override
1042        public void dumpGfxInfo(FileDescriptor fd, String[] args) {
1043            dumpGraphicsInfo(fd);
1044            WindowManagerImpl.getDefault().dumpGfxInfo(fd);
1045        }
1046
1047        @Override
1048        public void dumpDbInfo(FileDescriptor fd, String[] args) {
1049            PrintWriter pw = new PrintWriter(new FileOutputStream(fd));
1050            PrintWriterPrinter printer = new PrintWriterPrinter(pw);
1051            SQLiteDebug.dump(printer, args);
1052            pw.flush();
1053        }
1054
1055        private void printRow(PrintWriter pw, String format, Object...objs) {
1056            pw.println(String.format(format, objs));
1057        }
1058
1059        public void setCoreSettings(Bundle coreSettings) {
1060            queueOrSendMessage(H.SET_CORE_SETTINGS, coreSettings);
1061        }
1062
1063        public void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) {
1064            UpdateCompatibilityData ucd = new UpdateCompatibilityData();
1065            ucd.pkg = pkg;
1066            ucd.info = info;
1067            queueOrSendMessage(H.UPDATE_PACKAGE_COMPATIBILITY_INFO, ucd);
1068        }
1069
1070        public void scheduleTrimMemory(int level) {
1071            queueOrSendMessage(H.TRIM_MEMORY, null, level);
1072        }
1073
1074    }
1075
1076    private class H extends Handler {
1077        public static final int LAUNCH_ACTIVITY         = 100;
1078        public static final int PAUSE_ACTIVITY          = 101;
1079        public static final int PAUSE_ACTIVITY_FINISHING= 102;
1080        public static final int STOP_ACTIVITY_SHOW      = 103;
1081        public static final int STOP_ACTIVITY_HIDE      = 104;
1082        public static final int SHOW_WINDOW             = 105;
1083        public static final int HIDE_WINDOW             = 106;
1084        public static final int RESUME_ACTIVITY         = 107;
1085        public static final int SEND_RESULT             = 108;
1086        public static final int DESTROY_ACTIVITY        = 109;
1087        public static final int BIND_APPLICATION        = 110;
1088        public static final int EXIT_APPLICATION        = 111;
1089        public static final int NEW_INTENT              = 112;
1090        public static final int RECEIVER                = 113;
1091        public static final int CREATE_SERVICE          = 114;
1092        public static final int SERVICE_ARGS            = 115;
1093        public static final int STOP_SERVICE            = 116;
1094        public static final int REQUEST_THUMBNAIL       = 117;
1095        public static final int CONFIGURATION_CHANGED   = 118;
1096        public static final int CLEAN_UP_CONTEXT        = 119;
1097        public static final int GC_WHEN_IDLE            = 120;
1098        public static final int BIND_SERVICE            = 121;
1099        public static final int UNBIND_SERVICE          = 122;
1100        public static final int DUMP_SERVICE            = 123;
1101        public static final int LOW_MEMORY              = 124;
1102        public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
1103        public static final int RELAUNCH_ACTIVITY       = 126;
1104        public static final int PROFILER_CONTROL        = 127;
1105        public static final int CREATE_BACKUP_AGENT     = 128;
1106        public static final int DESTROY_BACKUP_AGENT    = 129;
1107        public static final int SUICIDE                 = 130;
1108        public static final int REMOVE_PROVIDER         = 131;
1109        public static final int ENABLE_JIT              = 132;
1110        public static final int DISPATCH_PACKAGE_BROADCAST = 133;
1111        public static final int SCHEDULE_CRASH          = 134;
1112        public static final int DUMP_HEAP               = 135;
1113        public static final int DUMP_ACTIVITY           = 136;
1114        public static final int SLEEPING                = 137;
1115        public static final int SET_CORE_SETTINGS       = 138;
1116        public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
1117        public static final int TRIM_MEMORY             = 140;
1118        public static final int DUMP_PROVIDER           = 141;
1119        String codeToString(int code) {
1120            if (DEBUG_MESSAGES) {
1121                switch (code) {
1122                    case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
1123                    case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
1124                    case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";
1125                    case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";
1126                    case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";
1127                    case SHOW_WINDOW: return "SHOW_WINDOW";
1128                    case HIDE_WINDOW: return "HIDE_WINDOW";
1129                    case RESUME_ACTIVITY: return "RESUME_ACTIVITY";
1130                    case SEND_RESULT: return "SEND_RESULT";
1131                    case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";
1132                    case BIND_APPLICATION: return "BIND_APPLICATION";
1133                    case EXIT_APPLICATION: return "EXIT_APPLICATION";
1134                    case NEW_INTENT: return "NEW_INTENT";
1135                    case RECEIVER: return "RECEIVER";
1136                    case CREATE_SERVICE: return "CREATE_SERVICE";
1137                    case SERVICE_ARGS: return "SERVICE_ARGS";
1138                    case STOP_SERVICE: return "STOP_SERVICE";
1139                    case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL";
1140                    case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
1141                    case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
1142                    case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
1143                    case BIND_SERVICE: return "BIND_SERVICE";
1144                    case UNBIND_SERVICE: return "UNBIND_SERVICE";
1145                    case DUMP_SERVICE: return "DUMP_SERVICE";
1146                    case LOW_MEMORY: return "LOW_MEMORY";
1147                    case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";
1148                    case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
1149                    case PROFILER_CONTROL: return "PROFILER_CONTROL";
1150                    case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
1151                    case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
1152                    case SUICIDE: return "SUICIDE";
1153                    case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
1154                    case ENABLE_JIT: return "ENABLE_JIT";
1155                    case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
1156                    case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
1157                    case DUMP_HEAP: return "DUMP_HEAP";
1158                    case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
1159                    case SLEEPING: return "SLEEPING";
1160                    case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS";
1161                    case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO";
1162                    case TRIM_MEMORY: return "TRIM_MEMORY";
1163                    case DUMP_PROVIDER: return "DUMP_PROVIDER";
1164                }
1165            }
1166            return "(unknown)";
1167        }
1168        public void handleMessage(Message msg) {
1169            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + msg.what);
1170            switch (msg.what) {
1171                case LAUNCH_ACTIVITY: {
1172                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
1173
1174                    r.packageInfo = getPackageInfoNoCheck(
1175                            r.activityInfo.applicationInfo, r.compatInfo);
1176                    handleLaunchActivity(r, null);
1177                } break;
1178                case RELAUNCH_ACTIVITY: {
1179                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
1180                    handleRelaunchActivity(r);
1181                } break;
1182                case PAUSE_ACTIVITY:
1183                    handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
1184                    maybeSnapshot();
1185                    break;
1186                case PAUSE_ACTIVITY_FINISHING:
1187                    handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);
1188                    break;
1189                case STOP_ACTIVITY_SHOW:
1190                    handleStopActivity((IBinder)msg.obj, true, msg.arg2);
1191                    break;
1192                case STOP_ACTIVITY_HIDE:
1193                    handleStopActivity((IBinder)msg.obj, false, msg.arg2);
1194                    break;
1195                case SHOW_WINDOW:
1196                    handleWindowVisibility((IBinder)msg.obj, true);
1197                    break;
1198                case HIDE_WINDOW:
1199                    handleWindowVisibility((IBinder)msg.obj, false);
1200                    break;
1201                case RESUME_ACTIVITY:
1202                    handleResumeActivity((IBinder)msg.obj, true,
1203                            msg.arg1 != 0);
1204                    break;
1205                case SEND_RESULT:
1206                    handleSendResult((ResultData)msg.obj);
1207                    break;
1208                case DESTROY_ACTIVITY:
1209                    handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
1210                            msg.arg2, false);
1211                    break;
1212                case BIND_APPLICATION:
1213                    AppBindData data = (AppBindData)msg.obj;
1214                    handleBindApplication(data);
1215                    break;
1216                case EXIT_APPLICATION:
1217                    if (mInitialApplication != null) {
1218                        mInitialApplication.onTerminate();
1219                    }
1220                    Looper.myLooper().quit();
1221                    break;
1222                case NEW_INTENT:
1223                    handleNewIntent((NewIntentData)msg.obj);
1224                    break;
1225                case RECEIVER:
1226                    handleReceiver((ReceiverData)msg.obj);
1227                    maybeSnapshot();
1228                    break;
1229                case CREATE_SERVICE:
1230                    handleCreateService((CreateServiceData)msg.obj);
1231                    break;
1232                case BIND_SERVICE:
1233                    handleBindService((BindServiceData)msg.obj);
1234                    break;
1235                case UNBIND_SERVICE:
1236                    handleUnbindService((BindServiceData)msg.obj);
1237                    break;
1238                case SERVICE_ARGS:
1239                    handleServiceArgs((ServiceArgsData)msg.obj);
1240                    break;
1241                case STOP_SERVICE:
1242                    handleStopService((IBinder)msg.obj);
1243                    maybeSnapshot();
1244                    break;
1245                case REQUEST_THUMBNAIL:
1246                    handleRequestThumbnail((IBinder)msg.obj);
1247                    break;
1248                case CONFIGURATION_CHANGED:
1249                    handleConfigurationChanged((Configuration)msg.obj, null);
1250                    break;
1251                case CLEAN_UP_CONTEXT:
1252                    ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
1253                    cci.context.performFinalCleanup(cci.who, cci.what);
1254                    break;
1255                case GC_WHEN_IDLE:
1256                    scheduleGcIdler();
1257                    break;
1258                case DUMP_SERVICE:
1259                    handleDumpService((DumpComponentInfo)msg.obj);
1260                    break;
1261                case LOW_MEMORY:
1262                    handleLowMemory();
1263                    break;
1264                case ACTIVITY_CONFIGURATION_CHANGED:
1265                    handleActivityConfigurationChanged((IBinder)msg.obj);
1266                    break;
1267                case PROFILER_CONTROL:
1268                    handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj, msg.arg2);
1269                    break;
1270                case CREATE_BACKUP_AGENT:
1271                    handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
1272                    break;
1273                case DESTROY_BACKUP_AGENT:
1274                    handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
1275                    break;
1276                case SUICIDE:
1277                    Process.killProcess(Process.myPid());
1278                    break;
1279                case REMOVE_PROVIDER:
1280                    completeRemoveProvider((IContentProvider)msg.obj);
1281                    break;
1282                case ENABLE_JIT:
1283                    ensureJitEnabled();
1284                    break;
1285                case DISPATCH_PACKAGE_BROADCAST:
1286                    handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
1287                    break;
1288                case SCHEDULE_CRASH:
1289                    throw new RemoteServiceException((String)msg.obj);
1290                case DUMP_HEAP:
1291                    handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj);
1292                    break;
1293                case DUMP_ACTIVITY:
1294                    handleDumpActivity((DumpComponentInfo)msg.obj);
1295                    break;
1296                case DUMP_PROVIDER:
1297                    handleDumpProvider((DumpComponentInfo)msg.obj);
1298                    break;
1299                case SLEEPING:
1300                    handleSleeping((IBinder)msg.obj, msg.arg1 != 0);
1301                    break;
1302                case SET_CORE_SETTINGS:
1303                    handleSetCoreSettings((Bundle) msg.obj);
1304                    break;
1305                case UPDATE_PACKAGE_COMPATIBILITY_INFO:
1306                    handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj);
1307                    break;
1308                case TRIM_MEMORY:
1309                    handleTrimMemory(msg.arg1);
1310                    break;
1311            }
1312            if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what);
1313        }
1314
1315        private void maybeSnapshot() {
1316            if (mBoundApplication != null && SamplingProfilerIntegration.isEnabled()) {
1317                // convert the *private* ActivityThread.PackageInfo to *public* known
1318                // android.content.pm.PackageInfo
1319                String packageName = mBoundApplication.info.mPackageName;
1320                android.content.pm.PackageInfo packageInfo = null;
1321                try {
1322                    Context context = getSystemContext();
1323                    if(context == null) {
1324                        Log.e(TAG, "cannot get a valid context");
1325                        return;
1326                    }
1327                    PackageManager pm = context.getPackageManager();
1328                    if(pm == null) {
1329                        Log.e(TAG, "cannot get a valid PackageManager");
1330                        return;
1331                    }
1332                    packageInfo = pm.getPackageInfo(
1333                            packageName, PackageManager.GET_ACTIVITIES);
1334                } catch (NameNotFoundException e) {
1335                    Log.e(TAG, "cannot get package info for " + packageName, e);
1336                }
1337                SamplingProfilerIntegration.writeSnapshot(mBoundApplication.processName, packageInfo);
1338            }
1339        }
1340    }
1341
1342    private class Idler implements MessageQueue.IdleHandler {
1343        public final boolean queueIdle() {
1344            ActivityClientRecord a = mNewActivities;
1345            boolean stopProfiling = false;
1346            if (mBoundApplication != null && mProfiler.profileFd != null
1347                    && mProfiler.autoStopProfiler) {
1348                stopProfiling = true;
1349            }
1350            if (a != null) {
1351                mNewActivities = null;
1352                IActivityManager am = ActivityManagerNative.getDefault();
1353                ActivityClientRecord prev;
1354                do {
1355                    if (localLOGV) Slog.v(
1356                        TAG, "Reporting idle of " + a +
1357                        " finished=" +
1358                        (a.activity != null && a.activity.mFinished));
1359                    if (a.activity != null && !a.activity.mFinished) {
1360                        try {
1361                            am.activityIdle(a.token, a.createdConfig, stopProfiling);
1362                            a.createdConfig = null;
1363                        } catch (RemoteException ex) {
1364                            // Ignore
1365                        }
1366                    }
1367                    prev = a;
1368                    a = a.nextIdle;
1369                    prev.nextIdle = null;
1370                } while (a != null);
1371            }
1372            if (stopProfiling) {
1373                mProfiler.stopProfiling();
1374            }
1375            ensureJitEnabled();
1376            return false;
1377        }
1378    }
1379
1380    final class GcIdler implements MessageQueue.IdleHandler {
1381        public final boolean queueIdle() {
1382            doGcIfNeeded();
1383            return false;
1384        }
1385    }
1386
1387    private static class ResourcesKey {
1388        final private String mResDir;
1389        final private float mScale;
1390        final private int mHash;
1391
1392        ResourcesKey(String resDir, float scale) {
1393            mResDir = resDir;
1394            mScale = scale;
1395            mHash = mResDir.hashCode() << 2 + (int) (mScale * 2);
1396        }
1397
1398        @Override
1399        public int hashCode() {
1400            return mHash;
1401        }
1402
1403        @Override
1404        public boolean equals(Object obj) {
1405            if (!(obj instanceof ResourcesKey)) {
1406                return false;
1407            }
1408            ResourcesKey peer = (ResourcesKey) obj;
1409            return mResDir.equals(peer.mResDir) && mScale == peer.mScale;
1410        }
1411    }
1412
1413    public static ActivityThread currentActivityThread() {
1414        return sThreadLocal.get();
1415    }
1416
1417    public static String currentPackageName() {
1418        ActivityThread am = currentActivityThread();
1419        return (am != null && am.mBoundApplication != null)
1420            ? am.mBoundApplication.processName : null;
1421    }
1422
1423    public static Application currentApplication() {
1424        ActivityThread am = currentActivityThread();
1425        return am != null ? am.mInitialApplication : null;
1426    }
1427
1428    public static IPackageManager getPackageManager() {
1429        if (sPackageManager != null) {
1430            //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
1431            return sPackageManager;
1432        }
1433        IBinder b = ServiceManager.getService("package");
1434        //Slog.v("PackageManager", "default service binder = " + b);
1435        sPackageManager = IPackageManager.Stub.asInterface(b);
1436        //Slog.v("PackageManager", "default service = " + sPackageManager);
1437        return sPackageManager;
1438    }
1439
1440    DisplayMetrics getDisplayMetricsLocked(CompatibilityInfo ci, boolean forceUpdate) {
1441        DisplayMetrics dm = mDisplayMetrics.get(ci);
1442        if (dm != null && !forceUpdate) {
1443            return dm;
1444        }
1445        if (dm == null) {
1446            dm = new DisplayMetrics();
1447            mDisplayMetrics.put(ci, dm);
1448        }
1449        Display d = WindowManagerImpl.getDefault(ci).getDefaultDisplay();
1450        d.getMetrics(dm);
1451        //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
1452        //        + metrics.heightPixels + " den=" + metrics.density
1453        //        + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
1454        return dm;
1455    }
1456
1457    static Configuration applyConfigCompat(Configuration config, CompatibilityInfo compat) {
1458        if (config == null) {
1459            return null;
1460        }
1461        if (compat != null && !compat.supportsScreen()) {
1462            config = new Configuration(config);
1463            compat.applyToConfiguration(config);
1464        }
1465        return config;
1466    }
1467
1468    private Configuration mMainThreadConfig = new Configuration();
1469    Configuration applyConfigCompatMainThread(Configuration config, CompatibilityInfo compat) {
1470        if (config == null) {
1471            return null;
1472        }
1473        if (compat != null && !compat.supportsScreen()) {
1474            mMainThreadConfig.setTo(config);
1475            config = mMainThreadConfig;
1476            compat.applyToConfiguration(config);
1477        }
1478        return config;
1479    }
1480
1481    /**
1482     * Creates the top level Resources for applications with the given compatibility info.
1483     *
1484     * @param resDir the resource directory.
1485     * @param compInfo the compability info. It will use the default compatibility info when it's
1486     * null.
1487     */
1488    Resources getTopLevelResources(String resDir, CompatibilityInfo compInfo) {
1489        ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale);
1490        Resources r;
1491        synchronized (mPackages) {
1492            // Resources is app scale dependent.
1493            if (false) {
1494                Slog.w(TAG, "getTopLevelResources: " + resDir + " / "
1495                        + compInfo.applicationScale);
1496            }
1497            WeakReference<Resources> wr = mActiveResources.get(key);
1498            r = wr != null ? wr.get() : null;
1499            //if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
1500            if (r != null && r.getAssets().isUpToDate()) {
1501                if (false) {
1502                    Slog.w(TAG, "Returning cached resources " + r + " " + resDir
1503                            + ": appScale=" + r.getCompatibilityInfo().applicationScale);
1504                }
1505                return r;
1506            }
1507        }
1508
1509        //if (r != null) {
1510        //    Slog.w(TAG, "Throwing away out-of-date resources!!!! "
1511        //            + r + " " + resDir);
1512        //}
1513
1514        AssetManager assets = new AssetManager();
1515        if (assets.addAssetPath(resDir) == 0) {
1516            return null;
1517        }
1518
1519        //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
1520        DisplayMetrics metrics = getDisplayMetricsLocked(null, false);
1521        r = new Resources(assets, metrics, getConfiguration(), compInfo);
1522        if (false) {
1523            Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
1524                    + r.getConfiguration() + " appScale="
1525                    + r.getCompatibilityInfo().applicationScale);
1526        }
1527
1528        synchronized (mPackages) {
1529            WeakReference<Resources> wr = mActiveResources.get(key);
1530            Resources existing = wr != null ? wr.get() : null;
1531            if (existing != null && existing.getAssets().isUpToDate()) {
1532                // Someone else already created the resources while we were
1533                // unlocked; go ahead and use theirs.
1534                r.getAssets().close();
1535                return existing;
1536            }
1537
1538            // XXX need to remove entries when weak references go away
1539            mActiveResources.put(key, new WeakReference<Resources>(r));
1540            return r;
1541        }
1542    }
1543
1544    /**
1545     * Creates the top level resources for the given package.
1546     */
1547    Resources getTopLevelResources(String resDir, LoadedApk pkgInfo) {
1548        return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo.get());
1549    }
1550
1551    final Handler getHandler() {
1552        return mH;
1553    }
1554
1555    public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
1556            int flags) {
1557        synchronized (mPackages) {
1558            WeakReference<LoadedApk> ref;
1559            if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) {
1560                ref = mPackages.get(packageName);
1561            } else {
1562                ref = mResourcePackages.get(packageName);
1563            }
1564            LoadedApk packageInfo = ref != null ? ref.get() : null;
1565            //Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo);
1566            //if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir
1567            //        + ": " + packageInfo.mResources.getAssets().isUpToDate());
1568            if (packageInfo != null && (packageInfo.mResources == null
1569                    || packageInfo.mResources.getAssets().isUpToDate())) {
1570                if (packageInfo.isSecurityViolation()
1571                        && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {
1572                    throw new SecurityException(
1573                            "Requesting code from " + packageName
1574                            + " to be run in process "
1575                            + mBoundApplication.processName
1576                            + "/" + mBoundApplication.appInfo.uid);
1577                }
1578                return packageInfo;
1579            }
1580        }
1581
1582        ApplicationInfo ai = null;
1583        try {
1584            ai = getPackageManager().getApplicationInfo(packageName,
1585                    PackageManager.GET_SHARED_LIBRARY_FILES);
1586        } catch (RemoteException e) {
1587            // Ignore
1588        }
1589
1590        if (ai != null) {
1591            return getPackageInfo(ai, compatInfo, flags);
1592        }
1593
1594        return null;
1595    }
1596
1597    public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo,
1598            int flags) {
1599        boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
1600        boolean securityViolation = includeCode && ai.uid != 0
1601                && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
1602                        ? !UserId.isSameApp(ai.uid, mBoundApplication.appInfo.uid)
1603                        : true);
1604        if ((flags&(Context.CONTEXT_INCLUDE_CODE
1605                |Context.CONTEXT_IGNORE_SECURITY))
1606                == Context.CONTEXT_INCLUDE_CODE) {
1607            if (securityViolation) {
1608                String msg = "Requesting code from " + ai.packageName
1609                        + " (with uid " + ai.uid + ")";
1610                if (mBoundApplication != null) {
1611                    msg = msg + " to be run in process "
1612                        + mBoundApplication.processName + " (with uid "
1613                        + mBoundApplication.appInfo.uid + ")";
1614                }
1615                throw new SecurityException(msg);
1616            }
1617        }
1618        return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode);
1619    }
1620
1621    public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
1622            CompatibilityInfo compatInfo) {
1623        return getPackageInfo(ai, compatInfo, null, false, true);
1624    }
1625
1626    public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) {
1627        synchronized (mPackages) {
1628            WeakReference<LoadedApk> ref;
1629            if (includeCode) {
1630                ref = mPackages.get(packageName);
1631            } else {
1632                ref = mResourcePackages.get(packageName);
1633            }
1634            return ref != null ? ref.get() : null;
1635        }
1636    }
1637
1638    private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
1639            ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
1640        synchronized (mPackages) {
1641            WeakReference<LoadedApk> ref;
1642            if (includeCode) {
1643                ref = mPackages.get(aInfo.packageName);
1644            } else {
1645                ref = mResourcePackages.get(aInfo.packageName);
1646            }
1647            LoadedApk packageInfo = ref != null ? ref.get() : null;
1648            if (packageInfo == null || (packageInfo.mResources != null
1649                    && !packageInfo.mResources.getAssets().isUpToDate())) {
1650                if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package "
1651                        : "Loading resource-only package ") + aInfo.packageName
1652                        + " (in " + (mBoundApplication != null
1653                                ? mBoundApplication.processName : null)
1654                        + ")");
1655                packageInfo =
1656                    new LoadedApk(this, aInfo, compatInfo, this, baseLoader,
1657                            securityViolation, includeCode &&
1658                            (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
1659                if (includeCode) {
1660                    mPackages.put(aInfo.packageName,
1661                            new WeakReference<LoadedApk>(packageInfo));
1662                } else {
1663                    mResourcePackages.put(aInfo.packageName,
1664                            new WeakReference<LoadedApk>(packageInfo));
1665                }
1666            }
1667            return packageInfo;
1668        }
1669    }
1670
1671    ActivityThread() {
1672    }
1673
1674    public ApplicationThread getApplicationThread()
1675    {
1676        return mAppThread;
1677    }
1678
1679    public Instrumentation getInstrumentation()
1680    {
1681        return mInstrumentation;
1682    }
1683
1684    public Configuration getConfiguration() {
1685        return mResConfiguration;
1686    }
1687
1688    public boolean isProfiling() {
1689        return mProfiler != null && mProfiler.profileFile != null
1690                && mProfiler.profileFd == null;
1691    }
1692
1693    public String getProfileFilePath() {
1694        return mProfiler.profileFile;
1695    }
1696
1697    public Looper getLooper() {
1698        return mLooper;
1699    }
1700
1701    public Application getApplication() {
1702        return mInitialApplication;
1703    }
1704
1705    public String getProcessName() {
1706        return mBoundApplication.processName;
1707    }
1708
1709    public ContextImpl getSystemContext() {
1710        synchronized (this) {
1711            if (mSystemContext == null) {
1712                ContextImpl context =
1713                    ContextImpl.createSystemContext(this);
1714                LoadedApk info = new LoadedApk(this, "android", context, null,
1715                        CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
1716                context.init(info, null, this);
1717                context.getResources().updateConfiguration(
1718                        getConfiguration(), getDisplayMetricsLocked(
1719                                CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, false));
1720                mSystemContext = context;
1721                //Slog.i(TAG, "Created system resources " + context.getResources()
1722                //        + ": " + context.getResources().getConfiguration());
1723            }
1724        }
1725        return mSystemContext;
1726    }
1727
1728    public void installSystemApplicationInfo(ApplicationInfo info) {
1729        synchronized (this) {
1730            ContextImpl context = getSystemContext();
1731            context.init(new LoadedApk(this, "android", context, info,
1732                    CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO), null, this);
1733
1734            // give ourselves a default profiler
1735            mProfiler = new Profiler();
1736        }
1737    }
1738
1739    void ensureJitEnabled() {
1740        if (!mJitEnabled) {
1741            mJitEnabled = true;
1742            dalvik.system.VMRuntime.getRuntime().startJitCompilation();
1743        }
1744    }
1745
1746    void scheduleGcIdler() {
1747        if (!mGcIdlerScheduled) {
1748            mGcIdlerScheduled = true;
1749            Looper.myQueue().addIdleHandler(mGcIdler);
1750        }
1751        mH.removeMessages(H.GC_WHEN_IDLE);
1752    }
1753
1754    void unscheduleGcIdler() {
1755        if (mGcIdlerScheduled) {
1756            mGcIdlerScheduled = false;
1757            Looper.myQueue().removeIdleHandler(mGcIdler);
1758        }
1759        mH.removeMessages(H.GC_WHEN_IDLE);
1760    }
1761
1762    void doGcIfNeeded() {
1763        mGcIdlerScheduled = false;
1764        final long now = SystemClock.uptimeMillis();
1765        //Slog.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime()
1766        //        + "m now=" + now);
1767        if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) {
1768            //Slog.i(TAG, "**** WE DO, WE DO WANT TO GC!");
1769            BinderInternal.forceGc("bg");
1770        }
1771    }
1772
1773    public void registerOnActivityPausedListener(Activity activity,
1774            OnActivityPausedListener listener) {
1775        synchronized (mOnPauseListeners) {
1776            ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity);
1777            if (list == null) {
1778                list = new ArrayList<OnActivityPausedListener>();
1779                mOnPauseListeners.put(activity, list);
1780            }
1781            list.add(listener);
1782        }
1783    }
1784
1785    public void unregisterOnActivityPausedListener(Activity activity,
1786            OnActivityPausedListener listener) {
1787        synchronized (mOnPauseListeners) {
1788            ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity);
1789            if (list != null) {
1790                list.remove(listener);
1791            }
1792        }
1793    }
1794
1795    public final ActivityInfo resolveActivityInfo(Intent intent) {
1796        ActivityInfo aInfo = intent.resolveActivityInfo(
1797                mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES);
1798        if (aInfo == null) {
1799            // Throw an exception.
1800            Instrumentation.checkStartActivityResult(
1801                    IActivityManager.START_CLASS_NOT_FOUND, intent);
1802        }
1803        return aInfo;
1804    }
1805
1806    public final Activity startActivityNow(Activity parent, String id,
1807        Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
1808        Activity.NonConfigurationInstances lastNonConfigurationInstances) {
1809        ActivityClientRecord r = new ActivityClientRecord();
1810            r.token = token;
1811            r.ident = 0;
1812            r.intent = intent;
1813            r.state = state;
1814            r.parent = parent;
1815            r.embeddedID = id;
1816            r.activityInfo = activityInfo;
1817            r.lastNonConfigurationInstances = lastNonConfigurationInstances;
1818        if (localLOGV) {
1819            ComponentName compname = intent.getComponent();
1820            String name;
1821            if (compname != null) {
1822                name = compname.toShortString();
1823            } else {
1824                name = "(Intent " + intent + ").getComponent() returned null";
1825            }
1826            Slog.v(TAG, "Performing launch: action=" + intent.getAction()
1827                    + ", comp=" + name
1828                    + ", token=" + token);
1829        }
1830        return performLaunchActivity(r, null);
1831    }
1832
1833    public final Activity getActivity(IBinder token) {
1834        return mActivities.get(token).activity;
1835    }
1836
1837    public final void sendActivityResult(
1838            IBinder token, String id, int requestCode,
1839            int resultCode, Intent data) {
1840        if (DEBUG_RESULTS) Slog.v(TAG, "sendActivityResult: id=" + id
1841                + " req=" + requestCode + " res=" + resultCode + " data=" + data);
1842        ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
1843        list.add(new ResultInfo(id, requestCode, resultCode, data));
1844        mAppThread.scheduleSendResult(token, list);
1845    }
1846
1847    // if the thread hasn't started yet, we don't have the handler, so just
1848    // save the messages until we're ready.
1849    private void queueOrSendMessage(int what, Object obj) {
1850        queueOrSendMessage(what, obj, 0, 0);
1851    }
1852
1853    private void queueOrSendMessage(int what, Object obj, int arg1) {
1854        queueOrSendMessage(what, obj, arg1, 0);
1855    }
1856
1857    private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
1858        synchronized (this) {
1859            if (DEBUG_MESSAGES) Slog.v(
1860                TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
1861                + ": " + arg1 + " / " + obj);
1862            Message msg = Message.obtain();
1863            msg.what = what;
1864            msg.obj = obj;
1865            msg.arg1 = arg1;
1866            msg.arg2 = arg2;
1867            mH.sendMessage(msg);
1868        }
1869    }
1870
1871    final void scheduleContextCleanup(ContextImpl context, String who,
1872            String what) {
1873        ContextCleanupInfo cci = new ContextCleanupInfo();
1874        cci.context = context;
1875        cci.who = who;
1876        cci.what = what;
1877        queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci);
1878    }
1879
1880    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
1881        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
1882
1883        ActivityInfo aInfo = r.activityInfo;
1884        if (r.packageInfo == null) {
1885            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
1886                    Context.CONTEXT_INCLUDE_CODE);
1887        }
1888
1889        ComponentName component = r.intent.getComponent();
1890        if (component == null) {
1891            component = r.intent.resolveActivity(
1892                mInitialApplication.getPackageManager());
1893            r.intent.setComponent(component);
1894        }
1895
1896        if (r.activityInfo.targetActivity != null) {
1897            component = new ComponentName(r.activityInfo.packageName,
1898                    r.activityInfo.targetActivity);
1899        }
1900
1901        Activity activity = null;
1902        try {
1903            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
1904            activity = mInstrumentation.newActivity(
1905                    cl, component.getClassName(), r.intent);
1906            StrictMode.incrementExpectedActivityCount(activity.getClass());
1907            r.intent.setExtrasClassLoader(cl);
1908            if (r.state != null) {
1909                r.state.setClassLoader(cl);
1910            }
1911        } catch (Exception e) {
1912            if (!mInstrumentation.onException(activity, e)) {
1913                throw new RuntimeException(
1914                    "Unable to instantiate activity " + component
1915                    + ": " + e.toString(), e);
1916            }
1917        }
1918
1919        try {
1920            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
1921
1922            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
1923            if (localLOGV) Slog.v(
1924                    TAG, r + ": app=" + app
1925                    + ", appName=" + app.getPackageName()
1926                    + ", pkg=" + r.packageInfo.getPackageName()
1927                    + ", comp=" + r.intent.getComponent().toShortString()
1928                    + ", dir=" + r.packageInfo.getAppDir());
1929
1930            if (activity != null) {
1931                ContextImpl appContext = new ContextImpl();
1932                appContext.init(r.packageInfo, r.token, this);
1933                appContext.setOuterContext(activity);
1934                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
1935                Configuration config = new Configuration(mCompatConfiguration);
1936                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
1937                        + r.activityInfo.name + " with config " + config);
1938                activity.attach(appContext, this, getInstrumentation(), r.token,
1939                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
1940                        r.embeddedID, r.lastNonConfigurationInstances, config);
1941
1942                if (customIntent != null) {
1943                    activity.mIntent = customIntent;
1944                }
1945                r.lastNonConfigurationInstances = null;
1946                activity.mStartedActivity = false;
1947                int theme = r.activityInfo.getThemeResource();
1948                if (theme != 0) {
1949                    activity.setTheme(theme);
1950                }
1951
1952                activity.mCalled = false;
1953                mInstrumentation.callActivityOnCreate(activity, r.state);
1954                if (!activity.mCalled) {
1955                    throw new SuperNotCalledException(
1956                        "Activity " + r.intent.getComponent().toShortString() +
1957                        " did not call through to super.onCreate()");
1958                }
1959                r.activity = activity;
1960                r.stopped = true;
1961                if (!r.activity.mFinished) {
1962                    activity.performStart();
1963                    r.stopped = false;
1964                }
1965                if (!r.activity.mFinished) {
1966                    if (r.state != null) {
1967                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
1968                    }
1969                }
1970                if (!r.activity.mFinished) {
1971                    activity.mCalled = false;
1972                    mInstrumentation.callActivityOnPostCreate(activity, r.state);
1973                    if (!activity.mCalled) {
1974                        throw new SuperNotCalledException(
1975                            "Activity " + r.intent.getComponent().toShortString() +
1976                            " did not call through to super.onPostCreate()");
1977                    }
1978                }
1979            }
1980            r.paused = true;
1981
1982            mActivities.put(r.token, r);
1983
1984        } catch (SuperNotCalledException e) {
1985            throw e;
1986
1987        } catch (Exception e) {
1988            if (!mInstrumentation.onException(activity, e)) {
1989                throw new RuntimeException(
1990                    "Unable to start activity " + component
1991                    + ": " + e.toString(), e);
1992            }
1993        }
1994
1995        return activity;
1996    }
1997
1998    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
1999        // If we are getting ready to gc after going to the background, well
2000        // we are back active so skip it.
2001        unscheduleGcIdler();
2002
2003        if (r.profileFd != null) {
2004            mProfiler.setProfiler(r.profileFile, r.profileFd);
2005            mProfiler.startProfiling();
2006            mProfiler.autoStopProfiler = r.autoStopProfiler;
2007        }
2008
2009        // Make sure we are running with the most recent config.
2010        handleConfigurationChanged(null, null);
2011
2012        if (localLOGV) Slog.v(
2013            TAG, "Handling launch of " + r);
2014        Activity a = performLaunchActivity(r, customIntent);
2015
2016        if (a != null) {
2017            r.createdConfig = new Configuration(mConfiguration);
2018            Bundle oldState = r.state;
2019            handleResumeActivity(r.token, false, r.isForward);
2020
2021            if (!r.activity.mFinished && r.startsNotResumed) {
2022                // The activity manager actually wants this one to start out
2023                // paused, because it needs to be visible but isn't in the
2024                // foreground.  We accomplish this by going through the
2025                // normal startup (because activities expect to go through
2026                // onResume() the first time they run, before their window
2027                // is displayed), and then pausing it.  However, in this case
2028                // we do -not- need to do the full pause cycle (of freezing
2029                // and such) because the activity manager assumes it can just
2030                // retain the current state it has.
2031                try {
2032                    r.activity.mCalled = false;
2033                    mInstrumentation.callActivityOnPause(r.activity);
2034                    // We need to keep around the original state, in case
2035                    // we need to be created again.
2036                    r.state = oldState;
2037                    if (!r.activity.mCalled) {
2038                        throw new SuperNotCalledException(
2039                            "Activity " + r.intent.getComponent().toShortString() +
2040                            " did not call through to super.onPause()");
2041                    }
2042
2043                } catch (SuperNotCalledException e) {
2044                    throw e;
2045
2046                } catch (Exception e) {
2047                    if (!mInstrumentation.onException(r.activity, e)) {
2048                        throw new RuntimeException(
2049                                "Unable to pause activity "
2050                                + r.intent.getComponent().toShortString()
2051                                + ": " + e.toString(), e);
2052                    }
2053                }
2054                r.paused = true;
2055            }
2056        } else {
2057            // If there was an error, for any reason, tell the activity
2058            // manager to stop us.
2059            try {
2060                ActivityManagerNative.getDefault()
2061                    .finishActivity(r.token, Activity.RESULT_CANCELED, null);
2062            } catch (RemoteException ex) {
2063                // Ignore
2064            }
2065        }
2066    }
2067
2068    private void deliverNewIntents(ActivityClientRecord r,
2069            List<Intent> intents) {
2070        final int N = intents.size();
2071        for (int i=0; i<N; i++) {
2072            Intent intent = intents.get(i);
2073            intent.setExtrasClassLoader(r.activity.getClassLoader());
2074            r.activity.mFragments.noteStateNotSaved();
2075            mInstrumentation.callActivityOnNewIntent(r.activity, intent);
2076        }
2077    }
2078
2079    public final void performNewIntents(IBinder token,
2080            List<Intent> intents) {
2081        ActivityClientRecord r = mActivities.get(token);
2082        if (r != null) {
2083            final boolean resumed = !r.paused;
2084            if (resumed) {
2085                r.activity.mTemporaryPause = true;
2086                mInstrumentation.callActivityOnPause(r.activity);
2087            }
2088            deliverNewIntents(r, intents);
2089            if (resumed) {
2090                r.activity.performResume();
2091                r.activity.mTemporaryPause = false;
2092            }
2093        }
2094    }
2095
2096    private void handleNewIntent(NewIntentData data) {
2097        performNewIntents(data.token, data.intents);
2098    }
2099
2100    private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>();
2101
2102    /**
2103     * Return the Intent that's currently being handled by a
2104     * BroadcastReceiver on this thread, or null if none.
2105     * @hide
2106     */
2107    public static Intent getIntentBeingBroadcast() {
2108        return sCurrentBroadcastIntent.get();
2109    }
2110
2111    private void handleReceiver(ReceiverData data) {
2112        // If we are getting ready to gc after going to the background, well
2113        // we are back active so skip it.
2114        unscheduleGcIdler();
2115
2116        String component = data.intent.getComponent().getClassName();
2117
2118        LoadedApk packageInfo = getPackageInfoNoCheck(
2119                data.info.applicationInfo, data.compatInfo);
2120
2121        IActivityManager mgr = ActivityManagerNative.getDefault();
2122
2123        BroadcastReceiver receiver;
2124        try {
2125            java.lang.ClassLoader cl = packageInfo.getClassLoader();
2126            data.intent.setExtrasClassLoader(cl);
2127            data.setExtrasClassLoader(cl);
2128            receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
2129        } catch (Exception e) {
2130            if (DEBUG_BROADCAST) Slog.i(TAG,
2131                    "Finishing failed broadcast to " + data.intent.getComponent());
2132            data.sendFinished(mgr);
2133            throw new RuntimeException(
2134                "Unable to instantiate receiver " + component
2135                + ": " + e.toString(), e);
2136        }
2137
2138        try {
2139            Application app = packageInfo.makeApplication(false, mInstrumentation);
2140
2141            if (localLOGV) Slog.v(
2142                TAG, "Performing receive of " + data.intent
2143                + ": app=" + app
2144                + ", appName=" + app.getPackageName()
2145                + ", pkg=" + packageInfo.getPackageName()
2146                + ", comp=" + data.intent.getComponent().toShortString()
2147                + ", dir=" + packageInfo.getAppDir());
2148
2149            ContextImpl context = (ContextImpl)app.getBaseContext();
2150            sCurrentBroadcastIntent.set(data.intent);
2151            receiver.setPendingResult(data);
2152            receiver.onReceive(context.getReceiverRestrictedContext(),
2153                    data.intent);
2154        } catch (Exception e) {
2155            if (DEBUG_BROADCAST) Slog.i(TAG,
2156                    "Finishing failed broadcast to " + data.intent.getComponent());
2157            data.sendFinished(mgr);
2158            if (!mInstrumentation.onException(receiver, e)) {
2159                throw new RuntimeException(
2160                    "Unable to start receiver " + component
2161                    + ": " + e.toString(), e);
2162            }
2163        } finally {
2164            sCurrentBroadcastIntent.set(null);
2165        }
2166
2167        if (receiver.getPendingResult() != null) {
2168            data.finish();
2169        }
2170    }
2171
2172    // Instantiate a BackupAgent and tell it that it's alive
2173    private void handleCreateBackupAgent(CreateBackupAgentData data) {
2174        if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data);
2175
2176        // no longer idle; we have backup work to do
2177        unscheduleGcIdler();
2178
2179        // instantiate the BackupAgent class named in the manifest
2180        LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
2181        String packageName = packageInfo.mPackageName;
2182        if (mBackupAgents.get(packageName) != null) {
2183            Slog.d(TAG, "BackupAgent " + "  for " + packageName
2184                    + " already exists");
2185            return;
2186        }
2187
2188        BackupAgent agent = null;
2189        String classname = data.appInfo.backupAgentName;
2190
2191        // full backup operation but no app-supplied agent?  use the default implementation
2192        if (classname == null && (data.backupMode == IApplicationThread.BACKUP_MODE_FULL
2193                || data.backupMode == IApplicationThread.BACKUP_MODE_RESTORE_FULL)) {
2194            classname = "android.app.backup.FullBackupAgent";
2195        }
2196
2197        try {
2198            IBinder binder = null;
2199            try {
2200                if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname);
2201
2202                java.lang.ClassLoader cl = packageInfo.getClassLoader();
2203                agent = (BackupAgent) cl.loadClass(classname).newInstance();
2204
2205                // set up the agent's context
2206                ContextImpl context = new ContextImpl();
2207                context.init(packageInfo, null, this);
2208                context.setOuterContext(agent);
2209                agent.attach(context);
2210
2211                agent.onCreate();
2212                binder = agent.onBind();
2213                mBackupAgents.put(packageName, agent);
2214            } catch (Exception e) {
2215                // If this is during restore, fail silently; otherwise go
2216                // ahead and let the user see the crash.
2217                Slog.e(TAG, "Agent threw during creation: " + e);
2218                if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE
2219                        && data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE_FULL) {
2220                    throw e;
2221                }
2222                // falling through with 'binder' still null
2223            }
2224
2225            // tell the OS that we're live now
2226            try {
2227                ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder);
2228            } catch (RemoteException e) {
2229                // nothing to do.
2230            }
2231        } catch (Exception e) {
2232            throw new RuntimeException("Unable to create BackupAgent "
2233                    + classname + ": " + e.toString(), e);
2234        }
2235    }
2236
2237    // Tear down a BackupAgent
2238    private void handleDestroyBackupAgent(CreateBackupAgentData data) {
2239        if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
2240
2241        LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
2242        String packageName = packageInfo.mPackageName;
2243        BackupAgent agent = mBackupAgents.get(packageName);
2244        if (agent != null) {
2245            try {
2246                agent.onDestroy();
2247            } catch (Exception e) {
2248                Slog.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo);
2249                e.printStackTrace();
2250            }
2251            mBackupAgents.remove(packageName);
2252        } else {
2253            Slog.w(TAG, "Attempt to destroy unknown backup agent " + data);
2254        }
2255    }
2256
2257    private void handleCreateService(CreateServiceData data) {
2258        // If we are getting ready to gc after going to the background, well
2259        // we are back active so skip it.
2260        unscheduleGcIdler();
2261
2262        LoadedApk packageInfo = getPackageInfoNoCheck(
2263                data.info.applicationInfo, data.compatInfo);
2264        Service service = null;
2265        try {
2266            java.lang.ClassLoader cl = packageInfo.getClassLoader();
2267            service = (Service) cl.loadClass(data.info.name).newInstance();
2268        } catch (Exception e) {
2269            if (!mInstrumentation.onException(service, e)) {
2270                throw new RuntimeException(
2271                    "Unable to instantiate service " + data.info.name
2272                    + ": " + e.toString(), e);
2273            }
2274        }
2275
2276        try {
2277            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
2278
2279            ContextImpl context = new ContextImpl();
2280            context.init(packageInfo, null, this);
2281
2282            Application app = packageInfo.makeApplication(false, mInstrumentation);
2283            context.setOuterContext(service);
2284            service.attach(context, this, data.info.name, data.token, app,
2285                    ActivityManagerNative.getDefault());
2286            service.onCreate();
2287            mServices.put(data.token, service);
2288            try {
2289                ActivityManagerNative.getDefault().serviceDoneExecuting(
2290                        data.token, 0, 0, 0);
2291            } catch (RemoteException e) {
2292                // nothing to do.
2293            }
2294        } catch (Exception e) {
2295            if (!mInstrumentation.onException(service, e)) {
2296                throw new RuntimeException(
2297                    "Unable to create service " + data.info.name
2298                    + ": " + e.toString(), e);
2299            }
2300        }
2301    }
2302
2303    private void handleBindService(BindServiceData data) {
2304        Service s = mServices.get(data.token);
2305        if (DEBUG_SERVICE)
2306            Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
2307        if (s != null) {
2308            try {
2309                data.intent.setExtrasClassLoader(s.getClassLoader());
2310                try {
2311                    if (!data.rebind) {
2312                        IBinder binder = s.onBind(data.intent);
2313                        ActivityManagerNative.getDefault().publishService(
2314                                data.token, data.intent, binder);
2315                    } else {
2316                        s.onRebind(data.intent);
2317                        ActivityManagerNative.getDefault().serviceDoneExecuting(
2318                                data.token, 0, 0, 0);
2319                    }
2320                    ensureJitEnabled();
2321                } catch (RemoteException ex) {
2322                }
2323            } catch (Exception e) {
2324                if (!mInstrumentation.onException(s, e)) {
2325                    throw new RuntimeException(
2326                            "Unable to bind to service " + s
2327                            + " with " + data.intent + ": " + e.toString(), e);
2328                }
2329            }
2330        }
2331    }
2332
2333    private void handleUnbindService(BindServiceData data) {
2334        Service s = mServices.get(data.token);
2335        if (s != null) {
2336            try {
2337                data.intent.setExtrasClassLoader(s.getClassLoader());
2338                boolean doRebind = s.onUnbind(data.intent);
2339                try {
2340                    if (doRebind) {
2341                        ActivityManagerNative.getDefault().unbindFinished(
2342                                data.token, data.intent, doRebind);
2343                    } else {
2344                        ActivityManagerNative.getDefault().serviceDoneExecuting(
2345                                data.token, 0, 0, 0);
2346                    }
2347                } catch (RemoteException ex) {
2348                }
2349            } catch (Exception e) {
2350                if (!mInstrumentation.onException(s, e)) {
2351                    throw new RuntimeException(
2352                            "Unable to unbind to service " + s
2353                            + " with " + data.intent + ": " + e.toString(), e);
2354                }
2355            }
2356        }
2357    }
2358
2359    private void handleDumpService(DumpComponentInfo info) {
2360        Service s = mServices.get(info.token);
2361        if (s != null) {
2362            PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
2363            s.dump(info.fd.getFileDescriptor(), pw, info.args);
2364            pw.flush();
2365            try {
2366                info.fd.close();
2367            } catch (IOException e) {
2368            }
2369        }
2370    }
2371
2372    private void handleDumpActivity(DumpComponentInfo info) {
2373        ActivityClientRecord r = mActivities.get(info.token);
2374        if (r != null && r.activity != null) {
2375            PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
2376            r.activity.dump(info.prefix, info.fd.getFileDescriptor(), pw, info.args);
2377            pw.flush();
2378            try {
2379                info.fd.close();
2380            } catch (IOException e) {
2381            }
2382        }
2383    }
2384
2385    private void handleDumpProvider(DumpComponentInfo info) {
2386        ProviderClientRecord r = mLocalProviders.get(info.token);
2387        if (r != null && r.mLocalProvider != null) {
2388            PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
2389            r.mLocalProvider.dump(info.fd.getFileDescriptor(), pw, info.args);
2390            pw.flush();
2391            try {
2392                info.fd.close();
2393            } catch (IOException e) {
2394            }
2395        }
2396    }
2397
2398    private void handleServiceArgs(ServiceArgsData data) {
2399        Service s = mServices.get(data.token);
2400        if (s != null) {
2401            try {
2402                if (data.args != null) {
2403                    data.args.setExtrasClassLoader(s.getClassLoader());
2404                }
2405                int res;
2406                if (!data.taskRemoved) {
2407                    res = s.onStartCommand(data.args, data.flags, data.startId);
2408                } else {
2409                    s.onTaskRemoved(data.args);
2410                    res = Service.START_TASK_REMOVED_COMPLETE;
2411                }
2412
2413                QueuedWork.waitToFinish();
2414
2415                try {
2416                    ActivityManagerNative.getDefault().serviceDoneExecuting(
2417                            data.token, 1, data.startId, res);
2418                } catch (RemoteException e) {
2419                    // nothing to do.
2420                }
2421                ensureJitEnabled();
2422            } catch (Exception e) {
2423                if (!mInstrumentation.onException(s, e)) {
2424                    throw new RuntimeException(
2425                            "Unable to start service " + s
2426                            + " with " + data.args + ": " + e.toString(), e);
2427                }
2428            }
2429        }
2430    }
2431
2432    private void handleStopService(IBinder token) {
2433        Service s = mServices.remove(token);
2434        if (s != null) {
2435            try {
2436                if (localLOGV) Slog.v(TAG, "Destroying service " + s);
2437                s.onDestroy();
2438                Context context = s.getBaseContext();
2439                if (context instanceof ContextImpl) {
2440                    final String who = s.getClassName();
2441                    ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
2442                }
2443
2444                QueuedWork.waitToFinish();
2445
2446                try {
2447                    ActivityManagerNative.getDefault().serviceDoneExecuting(
2448                            token, 0, 0, 0);
2449                } catch (RemoteException e) {
2450                    // nothing to do.
2451                }
2452            } catch (Exception e) {
2453                if (!mInstrumentation.onException(s, e)) {
2454                    throw new RuntimeException(
2455                            "Unable to stop service " + s
2456                            + ": " + e.toString(), e);
2457                }
2458            }
2459        }
2460        //Slog.i(TAG, "Running services: " + mServices);
2461    }
2462
2463    public final ActivityClientRecord performResumeActivity(IBinder token,
2464            boolean clearHide) {
2465        ActivityClientRecord r = mActivities.get(token);
2466        if (localLOGV) Slog.v(TAG, "Performing resume of " + r
2467                + " finished=" + r.activity.mFinished);
2468        if (r != null && !r.activity.mFinished) {
2469            if (clearHide) {
2470                r.hideForNow = false;
2471                r.activity.mStartedActivity = false;
2472            }
2473            try {
2474                if (r.pendingIntents != null) {
2475                    deliverNewIntents(r, r.pendingIntents);
2476                    r.pendingIntents = null;
2477                }
2478                if (r.pendingResults != null) {
2479                    deliverResults(r, r.pendingResults);
2480                    r.pendingResults = null;
2481                }
2482                r.activity.performResume();
2483
2484                EventLog.writeEvent(LOG_ON_RESUME_CALLED,
2485                        r.activity.getComponentName().getClassName());
2486
2487                r.paused = false;
2488                r.stopped = false;
2489                r.state = null;
2490            } catch (Exception e) {
2491                if (!mInstrumentation.onException(r.activity, e)) {
2492                    throw new RuntimeException(
2493                        "Unable to resume activity "
2494                        + r.intent.getComponent().toShortString()
2495                        + ": " + e.toString(), e);
2496                }
2497            }
2498        }
2499        return r;
2500    }
2501
2502    final void cleanUpPendingRemoveWindows(ActivityClientRecord r) {
2503        if (r.mPendingRemoveWindow != null) {
2504            r.mPendingRemoveWindowManager.removeViewImmediate(r.mPendingRemoveWindow);
2505            IBinder wtoken = r.mPendingRemoveWindow.getWindowToken();
2506            if (wtoken != null) {
2507                WindowManagerImpl.getDefault().closeAll(wtoken,
2508                        r.activity.getClass().getName(), "Activity");
2509            }
2510        }
2511        r.mPendingRemoveWindow = null;
2512        r.mPendingRemoveWindowManager = null;
2513    }
2514
2515    final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
2516        // If we are getting ready to gc after going to the background, well
2517        // we are back active so skip it.
2518        unscheduleGcIdler();
2519
2520        ActivityClientRecord r = performResumeActivity(token, clearHide);
2521
2522        if (r != null) {
2523            final Activity a = r.activity;
2524
2525            if (localLOGV) Slog.v(
2526                TAG, "Resume " + r + " started activity: " +
2527                a.mStartedActivity + ", hideForNow: " + r.hideForNow
2528                + ", finished: " + a.mFinished);
2529
2530            final int forwardBit = isForward ?
2531                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
2532
2533            // If the window hasn't yet been added to the window manager,
2534            // and this guy didn't finish itself or start another activity,
2535            // then go ahead and add the window.
2536            boolean willBeVisible = !a.mStartedActivity;
2537            if (!willBeVisible) {
2538                try {
2539                    willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
2540                            a.getActivityToken());
2541                } catch (RemoteException e) {
2542                }
2543            }
2544            if (r.window == null && !a.mFinished && willBeVisible) {
2545                r.window = r.activity.getWindow();
2546                View decor = r.window.getDecorView();
2547                decor.setVisibility(View.INVISIBLE);
2548                ViewManager wm = a.getWindowManager();
2549                WindowManager.LayoutParams l = r.window.getAttributes();
2550                a.mDecor = decor;
2551                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
2552                l.softInputMode |= forwardBit;
2553                if (a.mVisibleFromClient) {
2554                    a.mWindowAdded = true;
2555                    wm.addView(decor, l);
2556                }
2557
2558            // If the window has already been added, but during resume
2559            // we started another activity, then don't yet make the
2560            // window visible.
2561            } else if (!willBeVisible) {
2562                if (localLOGV) Slog.v(
2563                    TAG, "Launch " + r + " mStartedActivity set");
2564                r.hideForNow = true;
2565            }
2566
2567            // Get rid of anything left hanging around.
2568            cleanUpPendingRemoveWindows(r);
2569
2570            // The window is now visible if it has been added, we are not
2571            // simply finishing, and we are not starting another activity.
2572            if (!r.activity.mFinished && willBeVisible
2573                    && r.activity.mDecor != null && !r.hideForNow) {
2574                if (r.newConfig != null) {
2575                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
2576                            + r.activityInfo.name + " with newConfig " + r.newConfig);
2577                    performConfigurationChanged(r.activity, r.newConfig);
2578                    r.newConfig = null;
2579                }
2580                if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
2581                        + isForward);
2582                WindowManager.LayoutParams l = r.window.getAttributes();
2583                if ((l.softInputMode
2584                        & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
2585                        != forwardBit) {
2586                    l.softInputMode = (l.softInputMode
2587                            & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
2588                            | forwardBit;
2589                    if (r.activity.mVisibleFromClient) {
2590                        ViewManager wm = a.getWindowManager();
2591                        View decor = r.window.getDecorView();
2592                        wm.updateViewLayout(decor, l);
2593                    }
2594                }
2595                r.activity.mVisibleFromServer = true;
2596                mNumVisibleActivities++;
2597                if (r.activity.mVisibleFromClient) {
2598                    r.activity.makeVisible();
2599                }
2600            }
2601
2602            if (!r.onlyLocalRequest) {
2603                r.nextIdle = mNewActivities;
2604                mNewActivities = r;
2605                if (localLOGV) Slog.v(
2606                    TAG, "Scheduling idle handler for " + r);
2607                Looper.myQueue().addIdleHandler(new Idler());
2608            }
2609            r.onlyLocalRequest = false;
2610
2611        } else {
2612            // If an exception was thrown when trying to resume, then
2613            // just end this activity.
2614            try {
2615                ActivityManagerNative.getDefault()
2616                    .finishActivity(token, Activity.RESULT_CANCELED, null);
2617            } catch (RemoteException ex) {
2618            }
2619        }
2620    }
2621
2622    private int mThumbnailWidth = -1;
2623    private int mThumbnailHeight = -1;
2624    private Bitmap mAvailThumbnailBitmap = null;
2625    private Canvas mThumbnailCanvas = null;
2626
2627    private Bitmap createThumbnailBitmap(ActivityClientRecord r) {
2628        Bitmap thumbnail = mAvailThumbnailBitmap;
2629        try {
2630            if (thumbnail == null) {
2631                int w = mThumbnailWidth;
2632                int h;
2633                if (w < 0) {
2634                    Resources res = r.activity.getResources();
2635                    mThumbnailHeight = h =
2636                        res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
2637
2638                    mThumbnailWidth = w =
2639                        res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
2640                } else {
2641                    h = mThumbnailHeight;
2642                }
2643
2644                // On platforms where we don't want thumbnails, set dims to (0,0)
2645                if ((w > 0) && (h > 0)) {
2646                    thumbnail = Bitmap.createBitmap(w, h, THUMBNAIL_FORMAT);
2647                    thumbnail.eraseColor(0);
2648                }
2649            }
2650
2651            if (thumbnail != null) {
2652                Canvas cv = mThumbnailCanvas;
2653                if (cv == null) {
2654                    mThumbnailCanvas = cv = new Canvas();
2655                }
2656
2657                cv.setBitmap(thumbnail);
2658                if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
2659                    mAvailThumbnailBitmap = thumbnail;
2660                    thumbnail = null;
2661                }
2662                cv.setBitmap(null);
2663            }
2664
2665        } catch (Exception e) {
2666            if (!mInstrumentation.onException(r.activity, e)) {
2667                throw new RuntimeException(
2668                        "Unable to create thumbnail of "
2669                        + r.intent.getComponent().toShortString()
2670                        + ": " + e.toString(), e);
2671            }
2672            thumbnail = null;
2673        }
2674
2675        return thumbnail;
2676    }
2677
2678    private void handlePauseActivity(IBinder token, boolean finished,
2679            boolean userLeaving, int configChanges) {
2680        ActivityClientRecord r = mActivities.get(token);
2681        if (r != null) {
2682            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
2683            if (userLeaving) {
2684                performUserLeavingActivity(r);
2685            }
2686
2687            r.activity.mConfigChangeFlags |= configChanges;
2688            performPauseActivity(token, finished, r.isPreHoneycomb());
2689
2690            // Make sure any pending writes are now committed.
2691            if (r.isPreHoneycomb()) {
2692                QueuedWork.waitToFinish();
2693            }
2694
2695            // Tell the activity manager we have paused.
2696            try {
2697                ActivityManagerNative.getDefault().activityPaused(token);
2698            } catch (RemoteException ex) {
2699            }
2700        }
2701    }
2702
2703    final void performUserLeavingActivity(ActivityClientRecord r) {
2704        mInstrumentation.callActivityOnUserLeaving(r.activity);
2705    }
2706
2707    final Bundle performPauseActivity(IBinder token, boolean finished,
2708            boolean saveState) {
2709        ActivityClientRecord r = mActivities.get(token);
2710        return r != null ? performPauseActivity(r, finished, saveState) : null;
2711    }
2712
2713    final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
2714            boolean saveState) {
2715        if (r.paused) {
2716            if (r.activity.mFinished) {
2717                // If we are finishing, we won't call onResume() in certain cases.
2718                // So here we likewise don't want to call onPause() if the activity
2719                // isn't resumed.
2720                return null;
2721            }
2722            RuntimeException e = new RuntimeException(
2723                    "Performing pause of activity that is not resumed: "
2724                    + r.intent.getComponent().toShortString());
2725            Slog.e(TAG, e.getMessage(), e);
2726        }
2727        Bundle state = null;
2728        if (finished) {
2729            r.activity.mFinished = true;
2730        }
2731        try {
2732            // Next have the activity save its current state and managed dialogs...
2733            if (!r.activity.mFinished && saveState) {
2734                state = new Bundle();
2735                state.setAllowFds(false);
2736                mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
2737                r.state = state;
2738            }
2739            // Now we are idle.
2740            r.activity.mCalled = false;
2741            mInstrumentation.callActivityOnPause(r.activity);
2742            EventLog.writeEvent(LOG_ON_PAUSE_CALLED, r.activity.getComponentName().getClassName());
2743            if (!r.activity.mCalled) {
2744                throw new SuperNotCalledException(
2745                    "Activity " + r.intent.getComponent().toShortString() +
2746                    " did not call through to super.onPause()");
2747            }
2748
2749        } catch (SuperNotCalledException e) {
2750            throw e;
2751
2752        } catch (Exception e) {
2753            if (!mInstrumentation.onException(r.activity, e)) {
2754                throw new RuntimeException(
2755                        "Unable to pause activity "
2756                        + r.intent.getComponent().toShortString()
2757                        + ": " + e.toString(), e);
2758            }
2759        }
2760        r.paused = true;
2761
2762        // Notify any outstanding on paused listeners
2763        ArrayList<OnActivityPausedListener> listeners;
2764        synchronized (mOnPauseListeners) {
2765            listeners = mOnPauseListeners.remove(r.activity);
2766        }
2767        int size = (listeners != null ? listeners.size() : 0);
2768        for (int i = 0; i < size; i++) {
2769            listeners.get(i).onPaused(r.activity);
2770        }
2771
2772        return state;
2773    }
2774
2775    final void performStopActivity(IBinder token, boolean saveState) {
2776        ActivityClientRecord r = mActivities.get(token);
2777        performStopActivityInner(r, null, false, saveState);
2778    }
2779
2780    private static class StopInfo {
2781        Bitmap thumbnail;
2782        CharSequence description;
2783    }
2784
2785    private static final class ProviderRefCount {
2786        public int count;
2787
2788        ProviderRefCount(int pCount) {
2789            count = pCount;
2790        }
2791    }
2792
2793    /**
2794     * Core implementation of stopping an activity.  Note this is a little
2795     * tricky because the server's meaning of stop is slightly different
2796     * than our client -- for the server, stop means to save state and give
2797     * it the result when it is done, but the window may still be visible.
2798     * For the client, we want to call onStop()/onStart() to indicate when
2799     * the activity's UI visibillity changes.
2800     */
2801    private void performStopActivityInner(ActivityClientRecord r,
2802            StopInfo info, boolean keepShown, boolean saveState) {
2803        if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
2804        Bundle state = null;
2805        if (r != null) {
2806            if (!keepShown && r.stopped) {
2807                if (r.activity.mFinished) {
2808                    // If we are finishing, we won't call onResume() in certain
2809                    // cases.  So here we likewise don't want to call onStop()
2810                    // if the activity isn't resumed.
2811                    return;
2812                }
2813                RuntimeException e = new RuntimeException(
2814                        "Performing stop of activity that is not resumed: "
2815                        + r.intent.getComponent().toShortString());
2816                Slog.e(TAG, e.getMessage(), e);
2817            }
2818
2819            if (info != null) {
2820                try {
2821                    // First create a thumbnail for the activity...
2822                    // For now, don't create the thumbnail here; we are
2823                    // doing that by doing a screen snapshot.
2824                    info.thumbnail = null; //createThumbnailBitmap(r);
2825                    info.description = r.activity.onCreateDescription();
2826                } catch (Exception e) {
2827                    if (!mInstrumentation.onException(r.activity, e)) {
2828                        throw new RuntimeException(
2829                                "Unable to save state of activity "
2830                                + r.intent.getComponent().toShortString()
2831                                + ": " + e.toString(), e);
2832                    }
2833                }
2834            }
2835
2836            // Next have the activity save its current state and managed dialogs...
2837            if (!r.activity.mFinished && saveState) {
2838                if (r.state == null) {
2839                    state = new Bundle();
2840                    state.setAllowFds(false);
2841                    mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
2842                    r.state = state;
2843                } else {
2844                    state = r.state;
2845                }
2846            }
2847
2848            if (!keepShown) {
2849                try {
2850                    // Now we are idle.
2851                    r.activity.performStop();
2852                } catch (Exception e) {
2853                    if (!mInstrumentation.onException(r.activity, e)) {
2854                        throw new RuntimeException(
2855                                "Unable to stop activity "
2856                                + r.intent.getComponent().toShortString()
2857                                + ": " + e.toString(), e);
2858                    }
2859                }
2860                r.stopped = true;
2861            }
2862
2863            r.paused = true;
2864        }
2865    }
2866
2867    private void updateVisibility(ActivityClientRecord r, boolean show) {
2868        View v = r.activity.mDecor;
2869        if (v != null) {
2870            if (show) {
2871                if (!r.activity.mVisibleFromServer) {
2872                    r.activity.mVisibleFromServer = true;
2873                    mNumVisibleActivities++;
2874                    if (r.activity.mVisibleFromClient) {
2875                        r.activity.makeVisible();
2876                    }
2877                }
2878                if (r.newConfig != null) {
2879                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
2880                            + r.activityInfo.name + " with new config " + r.newConfig);
2881                    performConfigurationChanged(r.activity, r.newConfig);
2882                    r.newConfig = null;
2883                }
2884            } else {
2885                if (r.activity.mVisibleFromServer) {
2886                    r.activity.mVisibleFromServer = false;
2887                    mNumVisibleActivities--;
2888                    v.setVisibility(View.INVISIBLE);
2889                }
2890            }
2891        }
2892    }
2893
2894    private void handleStopActivity(IBinder token, boolean show, int configChanges) {
2895        ActivityClientRecord r = mActivities.get(token);
2896        r.activity.mConfigChangeFlags |= configChanges;
2897
2898        StopInfo info = new StopInfo();
2899        performStopActivityInner(r, info, show, true);
2900
2901        if (localLOGV) Slog.v(
2902            TAG, "Finishing stop of " + r + ": show=" + show
2903            + " win=" + r.window);
2904
2905        updateVisibility(r, show);
2906
2907        // Make sure any pending writes are now committed.
2908        if (!r.isPreHoneycomb()) {
2909            QueuedWork.waitToFinish();
2910        }
2911
2912        // Tell activity manager we have been stopped.
2913        try {
2914            ActivityManagerNative.getDefault().activityStopped(
2915                r.token, r.state, info.thumbnail, info.description);
2916        } catch (RemoteException ex) {
2917        }
2918    }
2919
2920    final void performRestartActivity(IBinder token) {
2921        ActivityClientRecord r = mActivities.get(token);
2922        if (r.stopped) {
2923            r.activity.performRestart();
2924            r.stopped = false;
2925        }
2926    }
2927
2928    private void handleWindowVisibility(IBinder token, boolean show) {
2929        ActivityClientRecord r = mActivities.get(token);
2930
2931        if (r == null) {
2932            Log.w(TAG, "handleWindowVisibility: no activity for token " + token);
2933            return;
2934        }
2935
2936        if (!show && !r.stopped) {
2937            performStopActivityInner(r, null, show, false);
2938        } else if (show && r.stopped) {
2939            // If we are getting ready to gc after going to the background, well
2940            // we are back active so skip it.
2941            unscheduleGcIdler();
2942
2943            r.activity.performRestart();
2944            r.stopped = false;
2945        }
2946        if (r.activity.mDecor != null) {
2947            if (false) Slog.v(
2948                TAG, "Handle window " + r + " visibility: " + show);
2949            updateVisibility(r, show);
2950        }
2951    }
2952
2953    private void handleSleeping(IBinder token, boolean sleeping) {
2954        ActivityClientRecord r = mActivities.get(token);
2955
2956        if (r == null) {
2957            Log.w(TAG, "handleSleeping: no activity for token " + token);
2958            return;
2959        }
2960
2961        if (sleeping) {
2962            if (!r.stopped && !r.isPreHoneycomb()) {
2963                try {
2964                    // Now we are idle.
2965                    r.activity.performStop();
2966                } catch (Exception e) {
2967                    if (!mInstrumentation.onException(r.activity, e)) {
2968                        throw new RuntimeException(
2969                                "Unable to stop activity "
2970                                + r.intent.getComponent().toShortString()
2971                                + ": " + e.toString(), e);
2972                    }
2973                }
2974                r.stopped = true;
2975            }
2976
2977            // Make sure any pending writes are now committed.
2978            if (!r.isPreHoneycomb()) {
2979                QueuedWork.waitToFinish();
2980            }
2981
2982            // Tell activity manager we slept.
2983            try {
2984                ActivityManagerNative.getDefault().activitySlept(r.token);
2985            } catch (RemoteException ex) {
2986            }
2987        } else {
2988            if (r.stopped && r.activity.mVisibleFromServer) {
2989                r.activity.performRestart();
2990                r.stopped = false;
2991            }
2992        }
2993    }
2994
2995    private void handleSetCoreSettings(Bundle coreSettings) {
2996        synchronized (mPackages) {
2997            mCoreSettings = coreSettings;
2998        }
2999    }
3000
3001    private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) {
3002        LoadedApk apk = peekPackageInfo(data.pkg, false);
3003        if (apk != null) {
3004            apk.mCompatibilityInfo.set(data.info);
3005        }
3006        apk = peekPackageInfo(data.pkg, true);
3007        if (apk != null) {
3008            apk.mCompatibilityInfo.set(data.info);
3009        }
3010        handleConfigurationChanged(mConfiguration, data.info);
3011        WindowManagerImpl.getDefault().reportNewConfiguration(mConfiguration);
3012    }
3013
3014    private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
3015        final int N = results.size();
3016        for (int i=0; i<N; i++) {
3017            ResultInfo ri = results.get(i);
3018            try {
3019                if (ri.mData != null) {
3020                    ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
3021                }
3022                if (DEBUG_RESULTS) Slog.v(TAG,
3023                        "Delivering result to activity " + r + " : " + ri);
3024                r.activity.dispatchActivityResult(ri.mResultWho,
3025                        ri.mRequestCode, ri.mResultCode, ri.mData);
3026            } catch (Exception e) {
3027                if (!mInstrumentation.onException(r.activity, e)) {
3028                    throw new RuntimeException(
3029                            "Failure delivering result " + ri + " to activity "
3030                            + r.intent.getComponent().toShortString()
3031                            + ": " + e.toString(), e);
3032                }
3033            }
3034        }
3035    }
3036
3037    private void handleSendResult(ResultData res) {
3038        ActivityClientRecord r = mActivities.get(res.token);
3039        if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
3040        if (r != null) {
3041            final boolean resumed = !r.paused;
3042            if (!r.activity.mFinished && r.activity.mDecor != null
3043                    && r.hideForNow && resumed) {
3044                // We had hidden the activity because it started another
3045                // one...  we have gotten a result back and we are not
3046                // paused, so make sure our window is visible.
3047                updateVisibility(r, true);
3048            }
3049            if (resumed) {
3050                try {
3051                    // Now we are idle.
3052                    r.activity.mCalled = false;
3053                    r.activity.mTemporaryPause = true;
3054                    mInstrumentation.callActivityOnPause(r.activity);
3055                    if (!r.activity.mCalled) {
3056                        throw new SuperNotCalledException(
3057                            "Activity " + r.intent.getComponent().toShortString()
3058                            + " did not call through to super.onPause()");
3059                    }
3060                } catch (SuperNotCalledException e) {
3061                    throw e;
3062                } catch (Exception e) {
3063                    if (!mInstrumentation.onException(r.activity, e)) {
3064                        throw new RuntimeException(
3065                                "Unable to pause activity "
3066                                + r.intent.getComponent().toShortString()
3067                                + ": " + e.toString(), e);
3068                    }
3069                }
3070            }
3071            deliverResults(r, res.results);
3072            if (resumed) {
3073                r.activity.performResume();
3074                r.activity.mTemporaryPause = false;
3075            }
3076        }
3077    }
3078
3079    public final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing) {
3080        return performDestroyActivity(token, finishing, 0, false);
3081    }
3082
3083    private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
3084            int configChanges, boolean getNonConfigInstance) {
3085        ActivityClientRecord r = mActivities.get(token);
3086        Class activityClass = null;
3087        if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
3088        if (r != null) {
3089            activityClass = r.activity.getClass();
3090            r.activity.mConfigChangeFlags |= configChanges;
3091            if (finishing) {
3092                r.activity.mFinished = true;
3093            }
3094            if (!r.paused) {
3095                try {
3096                    r.activity.mCalled = false;
3097                    mInstrumentation.callActivityOnPause(r.activity);
3098                    EventLog.writeEvent(LOG_ON_PAUSE_CALLED,
3099                            r.activity.getComponentName().getClassName());
3100                    if (!r.activity.mCalled) {
3101                        throw new SuperNotCalledException(
3102                            "Activity " + safeToComponentShortString(r.intent)
3103                            + " did not call through to super.onPause()");
3104                    }
3105                } catch (SuperNotCalledException e) {
3106                    throw e;
3107                } catch (Exception e) {
3108                    if (!mInstrumentation.onException(r.activity, e)) {
3109                        throw new RuntimeException(
3110                                "Unable to pause activity "
3111                                + safeToComponentShortString(r.intent)
3112                                + ": " + e.toString(), e);
3113                    }
3114                }
3115                r.paused = true;
3116            }
3117            if (!r.stopped) {
3118                try {
3119                    r.activity.performStop();
3120                } catch (SuperNotCalledException e) {
3121                    throw e;
3122                } catch (Exception e) {
3123                    if (!mInstrumentation.onException(r.activity, e)) {
3124                        throw new RuntimeException(
3125                                "Unable to stop activity "
3126                                + safeToComponentShortString(r.intent)
3127                                + ": " + e.toString(), e);
3128                    }
3129                }
3130                r.stopped = true;
3131            }
3132            if (getNonConfigInstance) {
3133                try {
3134                    r.lastNonConfigurationInstances
3135                            = r.activity.retainNonConfigurationInstances();
3136                } catch (Exception e) {
3137                    if (!mInstrumentation.onException(r.activity, e)) {
3138                        throw new RuntimeException(
3139                                "Unable to retain activity "
3140                                + r.intent.getComponent().toShortString()
3141                                + ": " + e.toString(), e);
3142                    }
3143                }
3144            }
3145            try {
3146                r.activity.mCalled = false;
3147                mInstrumentation.callActivityOnDestroy(r.activity);
3148                if (!r.activity.mCalled) {
3149                    throw new SuperNotCalledException(
3150                        "Activity " + safeToComponentShortString(r.intent) +
3151                        " did not call through to super.onDestroy()");
3152                }
3153                if (r.window != null) {
3154                    r.window.closeAllPanels();
3155                }
3156            } catch (SuperNotCalledException e) {
3157                throw e;
3158            } catch (Exception e) {
3159                if (!mInstrumentation.onException(r.activity, e)) {
3160                    throw new RuntimeException(
3161                            "Unable to destroy activity " + safeToComponentShortString(r.intent)
3162                            + ": " + e.toString(), e);
3163                }
3164            }
3165        }
3166        mActivities.remove(token);
3167        StrictMode.decrementExpectedActivityCount(activityClass);
3168        return r;
3169    }
3170
3171    private static String safeToComponentShortString(Intent intent) {
3172        ComponentName component = intent.getComponent();
3173        return component == null ? "[Unknown]" : component.toShortString();
3174    }
3175
3176    private void handleDestroyActivity(IBinder token, boolean finishing,
3177            int configChanges, boolean getNonConfigInstance) {
3178        ActivityClientRecord r = performDestroyActivity(token, finishing,
3179                configChanges, getNonConfigInstance);
3180        if (r != null) {
3181            cleanUpPendingRemoveWindows(r);
3182            WindowManager wm = r.activity.getWindowManager();
3183            View v = r.activity.mDecor;
3184            if (v != null) {
3185                if (r.activity.mVisibleFromServer) {
3186                    mNumVisibleActivities--;
3187                }
3188                IBinder wtoken = v.getWindowToken();
3189                if (r.activity.mWindowAdded) {
3190                    if (r.onlyLocalRequest) {
3191                        // Hold off on removing this until the new activity's
3192                        // window is being added.
3193                        r.mPendingRemoveWindow = v;
3194                        r.mPendingRemoveWindowManager = wm;
3195                    } else {
3196                        wm.removeViewImmediate(v);
3197                    }
3198                }
3199                if (wtoken != null && r.mPendingRemoveWindow == null) {
3200                    WindowManagerImpl.getDefault().closeAll(wtoken,
3201                            r.activity.getClass().getName(), "Activity");
3202                }
3203                r.activity.mDecor = null;
3204            }
3205            if (r.mPendingRemoveWindow == null) {
3206                // If we are delaying the removal of the activity window, then
3207                // we can't clean up all windows here.  Note that we can't do
3208                // so later either, which means any windows that aren't closed
3209                // by the app will leak.  Well we try to warning them a lot
3210                // about leaking windows, because that is a bug, so if they are
3211                // using this recreate facility then they get to live with leaks.
3212                WindowManagerImpl.getDefault().closeAll(token,
3213                        r.activity.getClass().getName(), "Activity");
3214            }
3215
3216            // Mocked out contexts won't be participating in the normal
3217            // process lifecycle, but if we're running with a proper
3218            // ApplicationContext we need to have it tear down things
3219            // cleanly.
3220            Context c = r.activity.getBaseContext();
3221            if (c instanceof ContextImpl) {
3222                ((ContextImpl) c).scheduleFinalCleanup(
3223                        r.activity.getClass().getName(), "Activity");
3224            }
3225        }
3226        if (finishing) {
3227            try {
3228                ActivityManagerNative.getDefault().activityDestroyed(token);
3229            } catch (RemoteException ex) {
3230                // If the system process has died, it's game over for everyone.
3231            }
3232        }
3233    }
3234
3235    public final void requestRelaunchActivity(IBinder token,
3236            List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
3237            int configChanges, boolean notResumed, Configuration config,
3238            boolean fromServer) {
3239        ActivityClientRecord target = null;
3240
3241        synchronized (mPackages) {
3242            for (int i=0; i<mRelaunchingActivities.size(); i++) {
3243                ActivityClientRecord r = mRelaunchingActivities.get(i);
3244                if (r.token == token) {
3245                    target = r;
3246                    if (pendingResults != null) {
3247                        if (r.pendingResults != null) {
3248                            r.pendingResults.addAll(pendingResults);
3249                        } else {
3250                            r.pendingResults = pendingResults;
3251                        }
3252                    }
3253                    if (pendingNewIntents != null) {
3254                        if (r.pendingIntents != null) {
3255                            r.pendingIntents.addAll(pendingNewIntents);
3256                        } else {
3257                            r.pendingIntents = pendingNewIntents;
3258                        }
3259                    }
3260                    break;
3261                }
3262            }
3263
3264            if (target == null) {
3265                target = new ActivityClientRecord();
3266                target.token = token;
3267                target.pendingResults = pendingResults;
3268                target.pendingIntents = pendingNewIntents;
3269                if (!fromServer) {
3270                    ActivityClientRecord existing = mActivities.get(token);
3271                    if (existing != null) {
3272                        target.startsNotResumed = existing.paused;
3273                    }
3274                    target.onlyLocalRequest = true;
3275                }
3276                mRelaunchingActivities.add(target);
3277                queueOrSendMessage(H.RELAUNCH_ACTIVITY, target);
3278            }
3279
3280            if (fromServer) {
3281                target.startsNotResumed = notResumed;
3282                target.onlyLocalRequest = false;
3283            }
3284            if (config != null) {
3285                target.createdConfig = config;
3286            }
3287            target.pendingConfigChanges |= configChanges;
3288        }
3289    }
3290
3291    private void handleRelaunchActivity(ActivityClientRecord tmp) {
3292        // If we are getting ready to gc after going to the background, well
3293        // we are back active so skip it.
3294        unscheduleGcIdler();
3295
3296        Configuration changedConfig = null;
3297        int configChanges = 0;
3298
3299        // First: make sure we have the most recent configuration and most
3300        // recent version of the activity, or skip it if some previous call
3301        // had taken a more recent version.
3302        synchronized (mPackages) {
3303            int N = mRelaunchingActivities.size();
3304            IBinder token = tmp.token;
3305            tmp = null;
3306            for (int i=0; i<N; i++) {
3307                ActivityClientRecord r = mRelaunchingActivities.get(i);
3308                if (r.token == token) {
3309                    tmp = r;
3310                    configChanges |= tmp.pendingConfigChanges;
3311                    mRelaunchingActivities.remove(i);
3312                    i--;
3313                    N--;
3314                }
3315            }
3316
3317            if (tmp == null) {
3318                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Abort, activity not relaunching!");
3319                return;
3320            }
3321
3322            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
3323                    + tmp.token + " with configChanges=0x"
3324                    + Integer.toHexString(configChanges));
3325
3326            if (mPendingConfiguration != null) {
3327                changedConfig = mPendingConfiguration;
3328                mPendingConfiguration = null;
3329            }
3330        }
3331
3332        if (tmp.createdConfig != null) {
3333            // If the activity manager is passing us its current config,
3334            // assume that is really what we want regardless of what we
3335            // may have pending.
3336            if (mConfiguration == null
3337                    || (tmp.createdConfig.isOtherSeqNewer(mConfiguration)
3338                            && mConfiguration.diff(tmp.createdConfig) != 0)) {
3339                if (changedConfig == null
3340                        || tmp.createdConfig.isOtherSeqNewer(changedConfig)) {
3341                    changedConfig = tmp.createdConfig;
3342                }
3343            }
3344        }
3345
3346        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
3347                + tmp.token + ": changedConfig=" + changedConfig);
3348
3349        // If there was a pending configuration change, execute it first.
3350        if (changedConfig != null) {
3351            handleConfigurationChanged(changedConfig, null);
3352        }
3353
3354        ActivityClientRecord r = mActivities.get(tmp.token);
3355        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r);
3356        if (r == null) {
3357            return;
3358        }
3359
3360        r.activity.mConfigChangeFlags |= configChanges;
3361        r.onlyLocalRequest = tmp.onlyLocalRequest;
3362        Intent currentIntent = r.activity.mIntent;
3363
3364        r.activity.mChangingConfigurations = true;
3365
3366        // Need to ensure state is saved.
3367        if (!r.paused) {
3368            performPauseActivity(r.token, false, r.isPreHoneycomb());
3369        }
3370        if (r.state == null && !r.stopped && !r.isPreHoneycomb()) {
3371            r.state = new Bundle();
3372            r.state.setAllowFds(false);
3373            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
3374        }
3375
3376        handleDestroyActivity(r.token, false, configChanges, true);
3377
3378        r.activity = null;
3379        r.window = null;
3380        r.hideForNow = false;
3381        r.nextIdle = null;
3382        // Merge any pending results and pending intents; don't just replace them
3383        if (tmp.pendingResults != null) {
3384            if (r.pendingResults == null) {
3385                r.pendingResults = tmp.pendingResults;
3386            } else {
3387                r.pendingResults.addAll(tmp.pendingResults);
3388            }
3389        }
3390        if (tmp.pendingIntents != null) {
3391            if (r.pendingIntents == null) {
3392                r.pendingIntents = tmp.pendingIntents;
3393            } else {
3394                r.pendingIntents.addAll(tmp.pendingIntents);
3395            }
3396        }
3397        r.startsNotResumed = tmp.startsNotResumed;
3398
3399        handleLaunchActivity(r, currentIntent);
3400    }
3401
3402    private void handleRequestThumbnail(IBinder token) {
3403        ActivityClientRecord r = mActivities.get(token);
3404        Bitmap thumbnail = createThumbnailBitmap(r);
3405        CharSequence description = null;
3406        try {
3407            description = r.activity.onCreateDescription();
3408        } catch (Exception e) {
3409            if (!mInstrumentation.onException(r.activity, e)) {
3410                throw new RuntimeException(
3411                        "Unable to create description of activity "
3412                        + r.intent.getComponent().toShortString()
3413                        + ": " + e.toString(), e);
3414            }
3415        }
3416        //System.out.println("Reporting top thumbnail " + thumbnail);
3417        try {
3418            ActivityManagerNative.getDefault().reportThumbnail(
3419                token, thumbnail, description);
3420        } catch (RemoteException ex) {
3421        }
3422    }
3423
3424    ArrayList<ComponentCallbacks2> collectComponentCallbacksLocked(
3425            boolean allActivities, Configuration newConfig) {
3426        ArrayList<ComponentCallbacks2> callbacks
3427                = new ArrayList<ComponentCallbacks2>();
3428
3429        if (mActivities.size() > 0) {
3430            Iterator<ActivityClientRecord> it = mActivities.values().iterator();
3431            while (it.hasNext()) {
3432                ActivityClientRecord ar = it.next();
3433                Activity a = ar.activity;
3434                if (a != null) {
3435                    Configuration thisConfig = applyConfigCompatMainThread(newConfig,
3436                            ar.packageInfo.mCompatibilityInfo.getIfNeeded());
3437                    if (!ar.activity.mFinished && (allActivities ||
3438                            (a != null && !ar.paused))) {
3439                        // If the activity is currently resumed, its configuration
3440                        // needs to change right now.
3441                        callbacks.add(a);
3442                    } else if (thisConfig != null) {
3443                        // Otherwise, we will tell it about the change
3444                        // the next time it is resumed or shown.  Note that
3445                        // the activity manager may, before then, decide the
3446                        // activity needs to be destroyed to handle its new
3447                        // configuration.
3448                        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Setting activity "
3449                                + ar.activityInfo.name + " newConfig=" + thisConfig);
3450                        ar.newConfig = thisConfig;
3451                    }
3452                }
3453            }
3454        }
3455        if (mServices.size() > 0) {
3456            Iterator<Service> it = mServices.values().iterator();
3457            while (it.hasNext()) {
3458                callbacks.add(it.next());
3459            }
3460        }
3461        synchronized (mProviderMap) {
3462            if (mLocalProviders.size() > 0) {
3463                Iterator<ProviderClientRecord> it = mLocalProviders.values().iterator();
3464                while (it.hasNext()) {
3465                    callbacks.add(it.next().mLocalProvider);
3466                }
3467            }
3468        }
3469        final int N = mAllApplications.size();
3470        for (int i=0; i<N; i++) {
3471            callbacks.add(mAllApplications.get(i));
3472        }
3473
3474        return callbacks;
3475    }
3476
3477    private final void performConfigurationChanged(
3478            ComponentCallbacks2 cb, Configuration config) {
3479        // Only for Activity objects, check that they actually call up to their
3480        // superclass implementation.  ComponentCallbacks2 is an interface, so
3481        // we check the runtime type and act accordingly.
3482        Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
3483        if (activity != null) {
3484            activity.mCalled = false;
3485        }
3486
3487        boolean shouldChangeConfig = false;
3488        if ((activity == null) || (activity.mCurrentConfig == null)) {
3489            shouldChangeConfig = true;
3490        } else {
3491
3492            // If the new config is the same as the config this Activity
3493            // is already running with then don't bother calling
3494            // onConfigurationChanged
3495            int diff = activity.mCurrentConfig.diff(config);
3496            if (diff != 0) {
3497                // If this activity doesn't handle any of the config changes
3498                // then don't bother calling onConfigurationChanged as we're
3499                // going to destroy it.
3500                if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0) {
3501                    shouldChangeConfig = true;
3502                }
3503            }
3504        }
3505
3506        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb
3507                + ": shouldChangeConfig=" + shouldChangeConfig);
3508        if (shouldChangeConfig) {
3509            cb.onConfigurationChanged(config);
3510
3511            if (activity != null) {
3512                if (!activity.mCalled) {
3513                    throw new SuperNotCalledException(
3514                            "Activity " + activity.getLocalClassName() +
3515                        " did not call through to super.onConfigurationChanged()");
3516                }
3517                activity.mConfigChangeFlags = 0;
3518                activity.mCurrentConfig = new Configuration(config);
3519            }
3520        }
3521    }
3522
3523    public final void applyConfigurationToResources(Configuration config) {
3524        synchronized (mPackages) {
3525            applyConfigurationToResourcesLocked(config, null);
3526        }
3527    }
3528
3529    final boolean applyConfigurationToResourcesLocked(Configuration config,
3530            CompatibilityInfo compat) {
3531        if (mResConfiguration == null) {
3532            mResConfiguration = new Configuration();
3533        }
3534        if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) {
3535            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
3536                    + mResConfiguration.seq + ", newSeq=" + config.seq);
3537            return false;
3538        }
3539        int changes = mResConfiguration.updateFrom(config);
3540        DisplayMetrics dm = getDisplayMetricsLocked(null, true);
3541
3542        if (compat != null && (mResCompatibilityInfo == null ||
3543                !mResCompatibilityInfo.equals(compat))) {
3544            mResCompatibilityInfo = compat;
3545            changes |= ActivityInfo.CONFIG_SCREEN_LAYOUT
3546                    | ActivityInfo.CONFIG_SCREEN_SIZE
3547                    | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
3548        }
3549
3550        // set it for java, this also affects newly created Resources
3551        if (config.locale != null) {
3552            Locale.setDefault(config.locale);
3553        }
3554
3555        Resources.updateSystemConfiguration(config, dm, compat);
3556
3557        ApplicationPackageManager.configurationChanged();
3558        //Slog.i(TAG, "Configuration changed in " + currentPackageName());
3559
3560        Iterator<WeakReference<Resources>> it =
3561            mActiveResources.values().iterator();
3562        //Iterator<Map.Entry<String, WeakReference<Resources>>> it =
3563        //    mActiveResources.entrySet().iterator();
3564        while (it.hasNext()) {
3565            WeakReference<Resources> v = it.next();
3566            Resources r = v.get();
3567            if (r != null) {
3568                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
3569                        + r + " config to: " + config);
3570                r.updateConfiguration(config, dm, compat);
3571                //Slog.i(TAG, "Updated app resources " + v.getKey()
3572                //        + " " + r + ": " + r.getConfiguration());
3573            } else {
3574                //Slog.i(TAG, "Removing old resources " + v.getKey());
3575                it.remove();
3576            }
3577        }
3578
3579        return changes != 0;
3580    }
3581
3582    final Configuration applyCompatConfiguration() {
3583        Configuration config = mConfiguration;
3584        if (mCompatConfiguration == null) {
3585            mCompatConfiguration = new Configuration();
3586        }
3587        mCompatConfiguration.setTo(mConfiguration);
3588        if (mResCompatibilityInfo != null && !mResCompatibilityInfo.supportsScreen()) {
3589            mResCompatibilityInfo.applyToConfiguration(mCompatConfiguration);
3590            config = mCompatConfiguration;
3591        }
3592        return config;
3593    }
3594
3595    final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {
3596
3597        ArrayList<ComponentCallbacks2> callbacks = null;
3598
3599        synchronized (mPackages) {
3600            if (mPendingConfiguration != null) {
3601                if (!mPendingConfiguration.isOtherSeqNewer(config)) {
3602                    config = mPendingConfiguration;
3603                }
3604                mPendingConfiguration = null;
3605            }
3606
3607            if (config == null) {
3608                return;
3609            }
3610
3611            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: "
3612                    + config);
3613
3614            applyConfigurationToResourcesLocked(config, compat);
3615
3616            if (mConfiguration == null) {
3617                mConfiguration = new Configuration();
3618            }
3619            if (!mConfiguration.isOtherSeqNewer(config) && compat == null) {
3620                return;
3621            }
3622            mConfiguration.updateFrom(config);
3623            config = applyCompatConfiguration();
3624            callbacks = collectComponentCallbacksLocked(false, config);
3625        }
3626
3627        // Cleanup hardware accelerated stuff
3628        WindowManagerImpl.getDefault().trimLocalMemory();
3629
3630        if (callbacks != null) {
3631            final int N = callbacks.size();
3632            for (int i=0; i<N; i++) {
3633                performConfigurationChanged(callbacks.get(i), config);
3634            }
3635        }
3636    }
3637
3638    final void handleActivityConfigurationChanged(IBinder token) {
3639        ActivityClientRecord r = mActivities.get(token);
3640        if (r == null || r.activity == null) {
3641            return;
3642        }
3643
3644        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
3645                + r.activityInfo.name);
3646
3647        performConfigurationChanged(r.activity, mCompatConfiguration);
3648    }
3649
3650    final void handleProfilerControl(boolean start, ProfilerControlData pcd, int profileType) {
3651        if (start) {
3652            try {
3653                switch (profileType) {
3654                    case 1:
3655                        ViewDebug.startLooperProfiling(pcd.path, pcd.fd.getFileDescriptor());
3656                        break;
3657                    default:
3658                        mProfiler.setProfiler(pcd.path, pcd.fd);
3659                        mProfiler.autoStopProfiler = false;
3660                        mProfiler.startProfiling();
3661                        break;
3662                }
3663            } catch (RuntimeException e) {
3664                Slog.w(TAG, "Profiling failed on path " + pcd.path
3665                        + " -- can the process access this path?");
3666            } finally {
3667                try {
3668                    pcd.fd.close();
3669                } catch (IOException e) {
3670                    Slog.w(TAG, "Failure closing profile fd", e);
3671                }
3672            }
3673        } else {
3674            switch (profileType) {
3675                case 1:
3676                    ViewDebug.stopLooperProfiling();
3677                    break;
3678                default:
3679                    mProfiler.stopProfiling();
3680                    break;
3681            }
3682        }
3683    }
3684
3685    final void handleDumpHeap(boolean managed, DumpHeapData dhd) {
3686        if (managed) {
3687            try {
3688                Debug.dumpHprofData(dhd.path, dhd.fd.getFileDescriptor());
3689            } catch (IOException e) {
3690                Slog.w(TAG, "Managed heap dump failed on path " + dhd.path
3691                        + " -- can the process access this path?");
3692            } finally {
3693                try {
3694                    dhd.fd.close();
3695                } catch (IOException e) {
3696                    Slog.w(TAG, "Failure closing profile fd", e);
3697                }
3698            }
3699        } else {
3700            Debug.dumpNativeHeap(dhd.fd.getFileDescriptor());
3701        }
3702    }
3703
3704    final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
3705        boolean hasPkgInfo = false;
3706        if (packages != null) {
3707            for (int i=packages.length-1; i>=0; i--) {
3708                //Slog.i(TAG, "Cleaning old package: " + packages[i]);
3709                if (!hasPkgInfo) {
3710                    WeakReference<LoadedApk> ref;
3711                    ref = mPackages.get(packages[i]);
3712                    if (ref != null && ref.get() != null) {
3713                        hasPkgInfo = true;
3714                    } else {
3715                        ref = mResourcePackages.get(packages[i]);
3716                        if (ref != null && ref.get() != null) {
3717                            hasPkgInfo = true;
3718                        }
3719                    }
3720                }
3721                mPackages.remove(packages[i]);
3722                mResourcePackages.remove(packages[i]);
3723            }
3724        }
3725        ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
3726                hasPkgInfo);
3727    }
3728
3729    final void handleLowMemory() {
3730        ArrayList<ComponentCallbacks2> callbacks;
3731
3732        synchronized (mPackages) {
3733            callbacks = collectComponentCallbacksLocked(true, null);
3734        }
3735
3736        final int N = callbacks.size();
3737        for (int i=0; i<N; i++) {
3738            callbacks.get(i).onLowMemory();
3739        }
3740
3741        // Ask SQLite to free up as much memory as it can, mostly from its page caches.
3742        if (Process.myUid() != Process.SYSTEM_UID) {
3743            int sqliteReleased = SQLiteDatabase.releaseMemory();
3744            EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
3745        }
3746
3747        // Ask graphics to free up as much as possible (font/image caches)
3748        Canvas.freeCaches();
3749
3750        BinderInternal.forceGc("mem");
3751    }
3752
3753    final void handleTrimMemory(int level) {
3754        ArrayList<ComponentCallbacks2> callbacks;
3755
3756        synchronized (mPackages) {
3757            callbacks = collectComponentCallbacksLocked(true, null);
3758        }
3759
3760        final int N = callbacks.size();
3761        for (int i=0; i<N; i++) {
3762            callbacks.get(i).onTrimMemory(level);
3763        }
3764        WindowManagerImpl.getDefault().trimMemory(level);
3765    }
3766
3767    private void setupGraphicsSupport(LoadedApk info) {
3768        if (Process.isIsolated()) {
3769            // Isolated processes aren't going to do UI.
3770            return;
3771        }
3772        try {
3773            int uid = Process.myUid();
3774            String[] packages = getPackageManager().getPackagesForUid(uid);
3775
3776            // If there are several packages in this application we won't
3777            // initialize the graphics disk caches
3778            if (packages != null && packages.length == 1) {
3779                ContextImpl appContext = new ContextImpl();
3780                appContext.init(info, null, this);
3781
3782                HardwareRenderer.setupDiskCache(appContext.getCacheDir());
3783                RenderScript.setupDiskCache(appContext.getCacheDir());
3784            }
3785        } catch (RemoteException e) {
3786            // Ignore
3787        }
3788    }
3789
3790    private void handleBindApplication(AppBindData data) {
3791        mBoundApplication = data;
3792        mConfiguration = new Configuration(data.config);
3793        mCompatConfiguration = new Configuration(data.config);
3794
3795        mProfiler = new Profiler();
3796        mProfiler.profileFile = data.initProfileFile;
3797        mProfiler.profileFd = data.initProfileFd;
3798        mProfiler.autoStopProfiler = data.initAutoStopProfiler;
3799
3800        // send up app name; do this *before* waiting for debugger
3801        Process.setArgV0(data.processName);
3802        android.ddm.DdmHandleAppName.setAppName(data.processName);
3803
3804        if (data.persistent) {
3805            // Persistent processes on low-memory devices do not get to
3806            // use hardware accelerated drawing, since this can add too much
3807            // overhead to the process.
3808            Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
3809            if (!ActivityManager.isHighEndGfx(display)) {
3810                HardwareRenderer.disable(false);
3811            }
3812        }
3813
3814        if (mProfiler.profileFd != null) {
3815            mProfiler.startProfiling();
3816        }
3817
3818        // If the app is Honeycomb MR1 or earlier, switch its AsyncTask
3819        // implementation to use the pool executor.  Normally, we use the
3820        // serialized executor as the default. This has to happen in the
3821        // main thread so the main looper is set right.
3822        if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
3823            AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
3824        }
3825
3826        /*
3827         * Before spawning a new process, reset the time zone to be the system time zone.
3828         * This needs to be done because the system time zone could have changed after the
3829         * the spawning of this process. Without doing this this process would have the incorrect
3830         * system time zone.
3831         */
3832        TimeZone.setDefault(null);
3833
3834        /*
3835         * Initialize the default locale in this process for the reasons we set the time zone.
3836         */
3837        Locale.setDefault(data.config.locale);
3838
3839        /*
3840         * Update the system configuration since its preloaded and might not
3841         * reflect configuration changes. The configuration object passed
3842         * in AppBindData can be safely assumed to be up to date
3843         */
3844        applyConfigurationToResourcesLocked(data.config, data.compatInfo);
3845        applyCompatConfiguration();
3846
3847        data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
3848
3849        setupGraphicsSupport(data.info);
3850
3851        /**
3852         * For system applications on userdebug/eng builds, log stack
3853         * traces of disk and network access to dropbox for analysis.
3854         */
3855        if ((data.appInfo.flags &
3856             (ApplicationInfo.FLAG_SYSTEM |
3857              ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) {
3858            StrictMode.conditionallyEnableDebugLogging();
3859        }
3860
3861        /**
3862         * For apps targetting SDK Honeycomb or later, we don't allow
3863         * network usage on the main event loop / UI thread.
3864         *
3865         * Note to those grepping:  this is what ultimately throws
3866         * NetworkOnMainThreadException ...
3867         */
3868        if (data.appInfo.targetSdkVersion > 9) {
3869            StrictMode.enableDeathOnNetwork();
3870        }
3871
3872        /**
3873         * Switch this process to density compatibility mode if needed.
3874         */
3875        if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
3876                == 0) {
3877            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
3878        }
3879
3880        if (data.debugMode != IApplicationThread.DEBUG_OFF) {
3881            // XXX should have option to change the port.
3882            Debug.changeDebugPort(8100);
3883            if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
3884                Slog.w(TAG, "Application " + data.info.getPackageName()
3885                      + " is waiting for the debugger on port 8100...");
3886
3887                IActivityManager mgr = ActivityManagerNative.getDefault();
3888                try {
3889                    mgr.showWaitingForDebugger(mAppThread, true);
3890                } catch (RemoteException ex) {
3891                }
3892
3893                Debug.waitForDebugger();
3894
3895                try {
3896                    mgr.showWaitingForDebugger(mAppThread, false);
3897                } catch (RemoteException ex) {
3898                }
3899
3900            } else {
3901                Slog.w(TAG, "Application " + data.info.getPackageName()
3902                      + " can be debugged on port 8100...");
3903            }
3904        }
3905
3906        /**
3907         * Initialize the default http proxy in this process for the reasons we set the time zone.
3908         */
3909        IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
3910        if (b != null) {
3911            // In pre-boot mode (doing initial launch to collect password), not
3912            // all system is up.  This includes the connectivity service, so don't
3913            // crash if we can't get it.
3914            IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
3915            try {
3916                ProxyProperties proxyProperties = service.getProxy();
3917                Proxy.setHttpProxySystemProperty(proxyProperties);
3918            } catch (RemoteException e) {}
3919        }
3920
3921        if (data.instrumentationName != null) {
3922            ContextImpl appContext = new ContextImpl();
3923            appContext.init(data.info, null, this);
3924            InstrumentationInfo ii = null;
3925            try {
3926                ii = appContext.getPackageManager().
3927                    getInstrumentationInfo(data.instrumentationName, 0);
3928            } catch (PackageManager.NameNotFoundException e) {
3929            }
3930            if (ii == null) {
3931                throw new RuntimeException(
3932                    "Unable to find instrumentation info for: "
3933                    + data.instrumentationName);
3934            }
3935
3936            mInstrumentationAppDir = ii.sourceDir;
3937            mInstrumentationAppPackage = ii.packageName;
3938            mInstrumentedAppDir = data.info.getAppDir();
3939
3940            ApplicationInfo instrApp = new ApplicationInfo();
3941            instrApp.packageName = ii.packageName;
3942            instrApp.sourceDir = ii.sourceDir;
3943            instrApp.publicSourceDir = ii.publicSourceDir;
3944            instrApp.dataDir = ii.dataDir;
3945            instrApp.nativeLibraryDir = ii.nativeLibraryDir;
3946            LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
3947                    appContext.getClassLoader(), false, true);
3948            ContextImpl instrContext = new ContextImpl();
3949            instrContext.init(pi, null, this);
3950
3951            try {
3952                java.lang.ClassLoader cl = instrContext.getClassLoader();
3953                mInstrumentation = (Instrumentation)
3954                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
3955            } catch (Exception e) {
3956                throw new RuntimeException(
3957                    "Unable to instantiate instrumentation "
3958                    + data.instrumentationName + ": " + e.toString(), e);
3959            }
3960
3961            mInstrumentation.init(this, instrContext, appContext,
3962                    new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);
3963
3964            if (mProfiler.profileFile != null && !ii.handleProfiling
3965                    && mProfiler.profileFd == null) {
3966                mProfiler.handlingProfiling = true;
3967                File file = new File(mProfiler.profileFile);
3968                file.getParentFile().mkdirs();
3969                Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
3970            }
3971
3972            try {
3973                mInstrumentation.onCreate(data.instrumentationArgs);
3974            }
3975            catch (Exception e) {
3976                throw new RuntimeException(
3977                    "Exception thrown in onCreate() of "
3978                    + data.instrumentationName + ": " + e.toString(), e);
3979            }
3980
3981        } else {
3982            mInstrumentation = new Instrumentation();
3983        }
3984
3985        if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
3986            dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
3987        }
3988
3989        // allow disk access during application and provider setup. this could
3990        // block processing ordered broadcasts, but later processing would
3991        // probably end up doing the same disk access. restore not guarded with
3992        // finally block, since exceptions here will take down the application.
3993        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
3994
3995        // If the app is being launched for full backup or restore, bring it up in
3996        // a restricted environment with the base application class.
3997        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
3998        mInitialApplication = app;
3999
4000        // don't bring up providers in restricted mode; they may depend on the
4001        // app's custom Application class
4002        if (!data.restrictedBackupMode) {
4003            List<ProviderInfo> providers = data.providers;
4004            if (providers != null) {
4005                installContentProviders(app, providers);
4006                // For process that contains content providers, we want to
4007                // ensure that the JIT is enabled "at some point".
4008                mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
4009            }
4010        }
4011
4012        try {
4013            mInstrumentation.callApplicationOnCreate(app);
4014        } catch (Exception e) {
4015            if (!mInstrumentation.onException(app, e)) {
4016                throw new RuntimeException(
4017                    "Unable to create application " + app.getClass().getName()
4018                    + ": " + e.toString(), e);
4019            }
4020        }
4021
4022        StrictMode.setThreadPolicy(savedPolicy);
4023    }
4024
4025    /*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
4026        IActivityManager am = ActivityManagerNative.getDefault();
4027        if (mProfiler.profileFile != null && mProfiler.handlingProfiling
4028                && mProfiler.profileFd == null) {
4029            Debug.stopMethodTracing();
4030        }
4031        //Slog.i(TAG, "am: " + ActivityManagerNative.getDefault()
4032        //      + ", app thr: " + mAppThread);
4033        try {
4034            am.finishInstrumentation(mAppThread, resultCode, results);
4035        } catch (RemoteException ex) {
4036        }
4037    }
4038
4039    private void installContentProviders(
4040            Context context, List<ProviderInfo> providers) {
4041        final ArrayList<IActivityManager.ContentProviderHolder> results =
4042            new ArrayList<IActivityManager.ContentProviderHolder>();
4043
4044        Iterator<ProviderInfo> i = providers.iterator();
4045        while (i.hasNext()) {
4046            ProviderInfo cpi = i.next();
4047            StringBuilder buf = new StringBuilder(128);
4048            buf.append("Pub ");
4049            buf.append(cpi.authority);
4050            buf.append(": ");
4051            buf.append(cpi.name);
4052            Log.i(TAG, buf.toString());
4053            IContentProvider cp = installProvider(context, null, cpi,
4054                    false /*noisy*/, true /*noReleaseNeeded*/);
4055            if (cp != null) {
4056                IActivityManager.ContentProviderHolder cph =
4057                        new IActivityManager.ContentProviderHolder(cpi);
4058                cph.provider = cp;
4059                cph.noReleaseNeeded = true;
4060                results.add(cph);
4061            }
4062        }
4063
4064        try {
4065            ActivityManagerNative.getDefault().publishContentProviders(
4066                getApplicationThread(), results);
4067        } catch (RemoteException ex) {
4068        }
4069    }
4070
4071    public final IContentProvider acquireProvider(Context c, String name) {
4072        IContentProvider provider = acquireExistingProvider(c, name);
4073        if (provider != null) {
4074            return provider;
4075        }
4076
4077        // There is a possible race here.  Another thread may try to acquire
4078        // the same provider at the same time.  When this happens, we want to ensure
4079        // that the first one wins.
4080        // Note that we cannot hold the lock while acquiring and installing the
4081        // provider since it might take a long time to run and it could also potentially
4082        // be re-entrant in the case where the provider is in the same process.
4083        IActivityManager.ContentProviderHolder holder = null;
4084        try {
4085            holder = ActivityManagerNative.getDefault().getContentProvider(
4086                    getApplicationThread(), name);
4087        } catch (RemoteException ex) {
4088        }
4089        if (holder == null) {
4090            Slog.e(TAG, "Failed to find provider info for " + name);
4091            return null;
4092        }
4093
4094        // Install provider will increment the reference count for us, and break
4095        // any ties in the race.
4096        provider = installProvider(c, holder.provider, holder.info,
4097                true /*noisy*/, holder.noReleaseNeeded);
4098        if (holder.provider != null && provider != holder.provider) {
4099            if (localLOGV) {
4100                Slog.v(TAG, "acquireProvider: lost the race, releasing extraneous "
4101                        + "reference to the content provider");
4102            }
4103            try {
4104                ActivityManagerNative.getDefault().removeContentProvider(
4105                        getApplicationThread(), name);
4106            } catch (RemoteException ex) {
4107            }
4108        }
4109        return provider;
4110    }
4111
4112    public final IContentProvider acquireExistingProvider(Context c, String name) {
4113        synchronized (mProviderMap) {
4114            ProviderClientRecord pr = mProviderMap.get(name);
4115            if (pr == null) {
4116                return null;
4117            }
4118
4119            IContentProvider provider = pr.mProvider;
4120            IBinder jBinder = provider.asBinder();
4121
4122            // Only increment the ref count if we have one.  If we don't then the
4123            // provider is not reference counted and never needs to be released.
4124            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4125            if (prc != null) {
4126                prc.count += 1;
4127                if (prc.count == 1) {
4128                    if (localLOGV) {
4129                        Slog.v(TAG, "acquireExistingProvider: "
4130                                + "snatched provider from the jaws of death");
4131                    }
4132                    // Because the provider previously had a reference count of zero,
4133                    // it was scheduled to be removed.  Cancel that.
4134                    mH.removeMessages(H.REMOVE_PROVIDER, provider);
4135                }
4136            }
4137            return provider;
4138        }
4139    }
4140
4141    public final boolean releaseProvider(IContentProvider provider) {
4142        if(provider == null) {
4143            return false;
4144        }
4145
4146        IBinder jBinder = provider.asBinder();
4147        synchronized (mProviderMap) {
4148            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4149            if (prc == null) {
4150                // The provider has no ref count, no release is needed.
4151                return false;
4152            }
4153
4154            if (prc.count == 0) {
4155                if (localLOGV) Slog.v(TAG, "releaseProvider: ref count already 0, how?");
4156                return false;
4157            }
4158
4159            prc.count -= 1;
4160            if (prc.count == 0) {
4161                // Schedule the actual remove asynchronously, since we don't know the context
4162                // this will be called in.
4163                // TODO: it would be nice to post a delayed message, so
4164                // if we come back and need the same provider quickly
4165                // we will still have it available.
4166                Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, provider);
4167                mH.sendMessage(msg);
4168            }
4169            return true;
4170        }
4171    }
4172
4173    final void completeRemoveProvider(IContentProvider provider) {
4174        IBinder jBinder = provider.asBinder();
4175        String remoteProviderName = null;
4176        synchronized(mProviderMap) {
4177            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4178            if (prc == null) {
4179                // Either no release is needed (so we shouldn't be here) or the
4180                // provider was already released.
4181                if (localLOGV) Slog.v(TAG, "completeRemoveProvider: release not needed");
4182                return;
4183            }
4184
4185            if (prc.count != 0) {
4186                // There was a race!  Some other client managed to acquire
4187                // the provider before the removal was completed.
4188                // Abort the removal.  We will do it later.
4189                if (localLOGV) Slog.v(TAG, "completeRemoveProvider: lost the race, "
4190                        + "provider still in use");
4191                return;
4192            }
4193
4194            mProviderRefCountMap.remove(jBinder);
4195
4196            Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator();
4197            while (iter.hasNext()) {
4198                ProviderClientRecord pr = iter.next();
4199                IBinder myBinder = pr.mProvider.asBinder();
4200                if (myBinder == jBinder) {
4201                    iter.remove();
4202                    if (pr.mLocalProvider == null) {
4203                        myBinder.unlinkToDeath(pr, 0);
4204                        if (remoteProviderName == null) {
4205                            remoteProviderName = pr.mName;
4206                        }
4207                    }
4208                }
4209            }
4210        }
4211
4212        if (remoteProviderName != null) {
4213            try {
4214                if (localLOGV) {
4215                    Slog.v(TAG, "removeProvider: Invoking ActivityManagerNative."
4216                            + "removeContentProvider(" + remoteProviderName + ")");
4217                }
4218                ActivityManagerNative.getDefault().removeContentProvider(
4219                        getApplicationThread(), remoteProviderName);
4220            } catch (RemoteException e) {
4221                //do nothing content provider object is dead any way
4222            }
4223        }
4224    }
4225
4226    final void removeDeadProvider(String name, IContentProvider provider) {
4227        synchronized(mProviderMap) {
4228            ProviderClientRecord pr = mProviderMap.get(name);
4229            if (pr != null && pr.mProvider.asBinder() == provider.asBinder()) {
4230                Slog.i(TAG, "Removing dead content provider: " + name);
4231                ProviderClientRecord removed = mProviderMap.remove(name);
4232                if (removed != null) {
4233                    removed.mProvider.asBinder().unlinkToDeath(removed, 0);
4234                }
4235            }
4236        }
4237    }
4238
4239    /**
4240     * Installs the provider.
4241     *
4242     * Providers that are local to the process or that come from the system server
4243     * may be installed permanently which is indicated by setting noReleaseNeeded to true.
4244     * Other remote providers are reference counted.  The initial reference count
4245     * for all reference counted providers is one.  Providers that are not reference
4246     * counted do not have a reference count (at all).
4247     *
4248     * This method detects when a provider has already been installed.  When this happens,
4249     * it increments the reference count of the existing provider (if appropriate)
4250     * and returns the existing provider.  This can happen due to concurrent
4251     * attempts to acquire the same provider.
4252     */
4253    private IContentProvider installProvider(Context context,
4254            IContentProvider provider, ProviderInfo info,
4255            boolean noisy, boolean noReleaseNeeded) {
4256        ContentProvider localProvider = null;
4257        if (provider == null) {
4258            if (noisy) {
4259                Slog.d(TAG, "Loading provider " + info.authority + ": "
4260                        + info.name);
4261            }
4262            Context c = null;
4263            ApplicationInfo ai = info.applicationInfo;
4264            if (context.getPackageName().equals(ai.packageName)) {
4265                c = context;
4266            } else if (mInitialApplication != null &&
4267                    mInitialApplication.getPackageName().equals(ai.packageName)) {
4268                c = mInitialApplication;
4269            } else {
4270                try {
4271                    c = context.createPackageContext(ai.packageName,
4272                            Context.CONTEXT_INCLUDE_CODE);
4273                } catch (PackageManager.NameNotFoundException e) {
4274                    // Ignore
4275                }
4276            }
4277            if (c == null) {
4278                Slog.w(TAG, "Unable to get context for package " +
4279                      ai.packageName +
4280                      " while loading content provider " +
4281                      info.name);
4282                return null;
4283            }
4284            try {
4285                final java.lang.ClassLoader cl = c.getClassLoader();
4286                localProvider = (ContentProvider)cl.
4287                    loadClass(info.name).newInstance();
4288                provider = localProvider.getIContentProvider();
4289                if (provider == null) {
4290                    Slog.e(TAG, "Failed to instantiate class " +
4291                          info.name + " from sourceDir " +
4292                          info.applicationInfo.sourceDir);
4293                    return null;
4294                }
4295                if (false) Slog.v(
4296                    TAG, "Instantiating local provider " + info.name);
4297                // XXX Need to create the correct context for this provider.
4298                localProvider.attachInfo(c, info);
4299            } catch (java.lang.Exception e) {
4300                if (!mInstrumentation.onException(null, e)) {
4301                    throw new RuntimeException(
4302                            "Unable to get provider " + info.name
4303                            + ": " + e.toString(), e);
4304                }
4305                return null;
4306            }
4307        } else if (localLOGV) {
4308            Slog.v(TAG, "Installing external provider " + info.authority + ": "
4309                    + info.name);
4310        }
4311
4312        synchronized (mProviderMap) {
4313            // There is a possibility that this thread raced with another thread to
4314            // add the provider.  If we find another thread got there first then we
4315            // just get out of the way and return the original provider.
4316            IBinder jBinder = provider.asBinder();
4317            String names[] = PATTERN_SEMICOLON.split(info.authority);
4318            for (int i = 0; i < names.length; i++) {
4319                ProviderClientRecord pr = mProviderMap.get(names[i]);
4320                if (pr != null) {
4321                    if (localLOGV) {
4322                        Slog.v(TAG, "installProvider: lost the race, "
4323                                + "using existing named provider");
4324                    }
4325                    provider = pr.mProvider;
4326                } else {
4327                    pr = new ProviderClientRecord(names[i], provider, localProvider);
4328                    if (localProvider == null) {
4329                        try {
4330                            jBinder.linkToDeath(pr, 0);
4331                        } catch (RemoteException e) {
4332                            // Provider already dead.  Bail out of here without making
4333                            // any changes to the provider map or other data structures.
4334                            return null;
4335                        }
4336                    }
4337                    mProviderMap.put(names[i], pr);
4338                }
4339            }
4340
4341            if (localProvider != null) {
4342                ProviderClientRecord pr = mLocalProviders.get(jBinder);
4343                if (pr != null) {
4344                    if (localLOGV) {
4345                        Slog.v(TAG, "installProvider: lost the race, "
4346                                + "using existing local provider");
4347                    }
4348                    provider = pr.mProvider;
4349                } else {
4350                    pr = new ProviderClientRecord(null, provider, localProvider);
4351                    mLocalProviders.put(jBinder, pr);
4352                }
4353            }
4354
4355            if (!noReleaseNeeded) {
4356                ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4357                if (prc != null) {
4358                    if (localLOGV) {
4359                        Slog.v(TAG, "installProvider: lost the race, incrementing ref count");
4360                    }
4361                    prc.count += 1;
4362                    if (prc.count == 1) {
4363                        if (localLOGV) {
4364                            Slog.v(TAG, "installProvider: "
4365                                    + "snatched provider from the jaws of death");
4366                        }
4367                        // Because the provider previously had a reference count of zero,
4368                        // it was scheduled to be removed.  Cancel that.
4369                        mH.removeMessages(H.REMOVE_PROVIDER, provider);
4370                    }
4371                } else {
4372                    mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
4373                }
4374            }
4375        }
4376        return provider;
4377    }
4378
4379    private void attach(boolean system) {
4380        sThreadLocal.set(this);
4381        mSystemThread = system;
4382        if (!system) {
4383            ViewRootImpl.addFirstDrawHandler(new Runnable() {
4384                public void run() {
4385                    ensureJitEnabled();
4386                }
4387            });
4388            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
4389            RuntimeInit.setApplicationObject(mAppThread.asBinder());
4390            IActivityManager mgr = ActivityManagerNative.getDefault();
4391            try {
4392                mgr.attachApplication(mAppThread);
4393            } catch (RemoteException ex) {
4394                // Ignore
4395            }
4396        } else {
4397            // Don't set application object here -- if the system crashes,
4398            // we can't display an alert, we just want to die die die.
4399            android.ddm.DdmHandleAppName.setAppName("system_process");
4400            try {
4401                mInstrumentation = new Instrumentation();
4402                ContextImpl context = new ContextImpl();
4403                context.init(getSystemContext().mPackageInfo, null, this);
4404                Application app = Instrumentation.newApplication(Application.class, context);
4405                mAllApplications.add(app);
4406                mInitialApplication = app;
4407                app.onCreate();
4408            } catch (Exception e) {
4409                throw new RuntimeException(
4410                        "Unable to instantiate Application():" + e.toString(), e);
4411            }
4412        }
4413
4414        ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
4415            public void onConfigurationChanged(Configuration newConfig) {
4416                synchronized (mPackages) {
4417                    // We need to apply this change to the resources
4418                    // immediately, because upon returning the view
4419                    // hierarchy will be informed about it.
4420                    if (applyConfigurationToResourcesLocked(newConfig, null)) {
4421                        // This actually changed the resources!  Tell
4422                        // everyone about it.
4423                        if (mPendingConfiguration == null ||
4424                                mPendingConfiguration.isOtherSeqNewer(newConfig)) {
4425                            mPendingConfiguration = newConfig;
4426
4427                            queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
4428                        }
4429                    }
4430                }
4431            }
4432            public void onLowMemory() {
4433            }
4434            public void onTrimMemory(int level) {
4435            }
4436        });
4437    }
4438
4439    public static ActivityThread systemMain() {
4440        HardwareRenderer.disable(true);
4441        ActivityThread thread = new ActivityThread();
4442        thread.attach(true);
4443        return thread;
4444    }
4445
4446    public final void installSystemProviders(List<ProviderInfo> providers) {
4447        if (providers != null) {
4448            installContentProviders(mInitialApplication, providers);
4449        }
4450    }
4451
4452    public int getIntCoreSetting(String key, int defaultValue) {
4453        synchronized (mPackages) {
4454            if (mCoreSettings != null) {
4455                return mCoreSettings.getInt(key, defaultValue);
4456            } else {
4457                return defaultValue;
4458            }
4459        }
4460    }
4461
4462    public static void main(String[] args) {
4463        SamplingProfilerIntegration.start();
4464
4465        // CloseGuard defaults to true and can be quite spammy.  We
4466        // disable it here, but selectively enable it later (via
4467        // StrictMode) on debug builds, but using DropBox, not logs.
4468        CloseGuard.setEnabled(false);
4469
4470        Process.setArgV0("<pre-initialized>");
4471
4472        Looper.prepareMainLooper();
4473        if (sMainThreadHandler == null) {
4474            sMainThreadHandler = new Handler();
4475        }
4476
4477        ActivityThread thread = new ActivityThread();
4478        thread.attach(false);
4479
4480        AsyncTask.init();
4481
4482        if (false) {
4483            Looper.myLooper().setMessageLogging(new
4484                    LogPrinter(Log.DEBUG, "ActivityThread"));
4485        }
4486
4487        Looper.loop();
4488
4489        throw new RuntimeException("Main thread loop unexpectedly exited");
4490    }
4491}
4492