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