ActivityThread.java revision 84193b198f454c85c76e3ac0340a566f4a944f74
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);
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
2179            if (!r.activity.mFinished && r.startsNotResumed) {
2180                // The activity manager actually wants this one to start out
2181                // paused, because it needs to be visible but isn't in the
2182                // foreground.  We accomplish this by going through the
2183                // normal startup (because activities expect to go through
2184                // onResume() the first time they run, before their window
2185                // is displayed), and then pausing it.  However, in this case
2186                // we do -not- need to do the full pause cycle (of freezing
2187                // and such) because the activity manager assumes it can just
2188                // retain the current state it has.
2189                try {
2190                    r.activity.mCalled = false;
2191                    mInstrumentation.callActivityOnPause(r.activity);
2192                    // We need to keep around the original state, in case
2193                    // we need to be created again.  But we only do this
2194                    // for pre-Honeycomb apps, which always save their state
2195                    // when pausing, so we can not have them save their state
2196                    // when restarting from a paused state.  For HC and later,
2197                    // we want to (and can) let the state be saved as the normal
2198                    // part of stopping the activity.
2199                    if (r.isPreHoneycomb()) {
2200                        r.state = oldState;
2201                    }
2202                    if (!r.activity.mCalled) {
2203                        throw new SuperNotCalledException(
2204                            "Activity " + r.intent.getComponent().toShortString() +
2205                            " did not call through to super.onPause()");
2206                    }
2207
2208                } catch (SuperNotCalledException e) {
2209                    throw e;
2210
2211                } catch (Exception e) {
2212                    if (!mInstrumentation.onException(r.activity, e)) {
2213                        throw new RuntimeException(
2214                                "Unable to pause activity "
2215                                + r.intent.getComponent().toShortString()
2216                                + ": " + e.toString(), e);
2217                    }
2218                }
2219                r.paused = true;
2220            }
2221        } else {
2222            // If there was an error, for any reason, tell the activity
2223            // manager to stop us.
2224            try {
2225                ActivityManagerNative.getDefault()
2226                    .finishActivity(r.token, Activity.RESULT_CANCELED, null);
2227            } catch (RemoteException ex) {
2228                // Ignore
2229            }
2230        }
2231    }
2232
2233    private void deliverNewIntents(ActivityClientRecord r,
2234            List<Intent> intents) {
2235        final int N = intents.size();
2236        for (int i=0; i<N; i++) {
2237            Intent intent = intents.get(i);
2238            intent.setExtrasClassLoader(r.activity.getClassLoader());
2239            r.activity.mFragments.noteStateNotSaved();
2240            mInstrumentation.callActivityOnNewIntent(r.activity, intent);
2241        }
2242    }
2243
2244    public final void performNewIntents(IBinder token,
2245            List<Intent> intents) {
2246        ActivityClientRecord r = mActivities.get(token);
2247        if (r != null) {
2248            final boolean resumed = !r.paused;
2249            if (resumed) {
2250                r.activity.mTemporaryPause = true;
2251                mInstrumentation.callActivityOnPause(r.activity);
2252            }
2253            deliverNewIntents(r, intents);
2254            if (resumed) {
2255                r.activity.performResume();
2256                r.activity.mTemporaryPause = false;
2257            }
2258        }
2259    }
2260
2261    private void handleNewIntent(NewIntentData data) {
2262        performNewIntents(data.token, data.intents);
2263    }
2264
2265    private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>();
2266
2267    /**
2268     * Return the Intent that's currently being handled by a
2269     * BroadcastReceiver on this thread, or null if none.
2270     * @hide
2271     */
2272    public static Intent getIntentBeingBroadcast() {
2273        return sCurrentBroadcastIntent.get();
2274    }
2275
2276    private void handleReceiver(ReceiverData data) {
2277        // If we are getting ready to gc after going to the background, well
2278        // we are back active so skip it.
2279        unscheduleGcIdler();
2280
2281        String component = data.intent.getComponent().getClassName();
2282
2283        LoadedApk packageInfo = getPackageInfoNoCheck(
2284                data.info.applicationInfo, data.compatInfo);
2285
2286        IActivityManager mgr = ActivityManagerNative.getDefault();
2287
2288        BroadcastReceiver receiver;
2289        try {
2290            java.lang.ClassLoader cl = packageInfo.getClassLoader();
2291            data.intent.setExtrasClassLoader(cl);
2292            data.setExtrasClassLoader(cl);
2293            receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
2294        } catch (Exception e) {
2295            if (DEBUG_BROADCAST) Slog.i(TAG,
2296                    "Finishing failed broadcast to " + data.intent.getComponent());
2297            data.sendFinished(mgr);
2298            throw new RuntimeException(
2299                "Unable to instantiate receiver " + component
2300                + ": " + e.toString(), e);
2301        }
2302
2303        try {
2304            Application app = packageInfo.makeApplication(false, mInstrumentation);
2305
2306            if (localLOGV) Slog.v(
2307                TAG, "Performing receive of " + data.intent
2308                + ": app=" + app
2309                + ", appName=" + app.getPackageName()
2310                + ", pkg=" + packageInfo.getPackageName()
2311                + ", comp=" + data.intent.getComponent().toShortString()
2312                + ", dir=" + packageInfo.getAppDir());
2313
2314            ContextImpl context = (ContextImpl)app.getBaseContext();
2315            sCurrentBroadcastIntent.set(data.intent);
2316            receiver.setPendingResult(data);
2317            receiver.onReceive(context.getReceiverRestrictedContext(),
2318                    data.intent);
2319        } catch (Exception e) {
2320            if (DEBUG_BROADCAST) Slog.i(TAG,
2321                    "Finishing failed broadcast to " + data.intent.getComponent());
2322            data.sendFinished(mgr);
2323            if (!mInstrumentation.onException(receiver, e)) {
2324                throw new RuntimeException(
2325                    "Unable to start receiver " + component
2326                    + ": " + e.toString(), e);
2327            }
2328        } finally {
2329            sCurrentBroadcastIntent.set(null);
2330        }
2331
2332        if (receiver.getPendingResult() != null) {
2333            data.finish();
2334        }
2335    }
2336
2337    // Instantiate a BackupAgent and tell it that it's alive
2338    private void handleCreateBackupAgent(CreateBackupAgentData data) {
2339        if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data);
2340
2341        // no longer idle; we have backup work to do
2342        unscheduleGcIdler();
2343
2344        // instantiate the BackupAgent class named in the manifest
2345        LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
2346        String packageName = packageInfo.mPackageName;
2347        if (mBackupAgents.get(packageName) != null) {
2348            Slog.d(TAG, "BackupAgent " + "  for " + packageName
2349                    + " already exists");
2350            return;
2351        }
2352
2353        BackupAgent agent = null;
2354        String classname = data.appInfo.backupAgentName;
2355
2356        // full backup operation but no app-supplied agent?  use the default implementation
2357        if (classname == null && (data.backupMode == IApplicationThread.BACKUP_MODE_FULL
2358                || data.backupMode == IApplicationThread.BACKUP_MODE_RESTORE_FULL)) {
2359            classname = "android.app.backup.FullBackupAgent";
2360        }
2361
2362        try {
2363            IBinder binder = null;
2364            try {
2365                if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname);
2366
2367                java.lang.ClassLoader cl = packageInfo.getClassLoader();
2368                agent = (BackupAgent) cl.loadClass(classname).newInstance();
2369
2370                // set up the agent's context
2371                ContextImpl context = new ContextImpl();
2372                context.init(packageInfo, null, this);
2373                context.setOuterContext(agent);
2374                agent.attach(context);
2375
2376                agent.onCreate();
2377                binder = agent.onBind();
2378                mBackupAgents.put(packageName, agent);
2379            } catch (Exception e) {
2380                // If this is during restore, fail silently; otherwise go
2381                // ahead and let the user see the crash.
2382                Slog.e(TAG, "Agent threw during creation: " + e);
2383                if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE
2384                        && data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE_FULL) {
2385                    throw e;
2386                }
2387                // falling through with 'binder' still null
2388            }
2389
2390            // tell the OS that we're live now
2391            try {
2392                ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder);
2393            } catch (RemoteException e) {
2394                // nothing to do.
2395            }
2396        } catch (Exception e) {
2397            throw new RuntimeException("Unable to create BackupAgent "
2398                    + classname + ": " + e.toString(), e);
2399        }
2400    }
2401
2402    // Tear down a BackupAgent
2403    private void handleDestroyBackupAgent(CreateBackupAgentData data) {
2404        if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
2405
2406        LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
2407        String packageName = packageInfo.mPackageName;
2408        BackupAgent agent = mBackupAgents.get(packageName);
2409        if (agent != null) {
2410            try {
2411                agent.onDestroy();
2412            } catch (Exception e) {
2413                Slog.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo);
2414                e.printStackTrace();
2415            }
2416            mBackupAgents.remove(packageName);
2417        } else {
2418            Slog.w(TAG, "Attempt to destroy unknown backup agent " + data);
2419        }
2420    }
2421
2422    private void handleCreateService(CreateServiceData data) {
2423        // If we are getting ready to gc after going to the background, well
2424        // we are back active so skip it.
2425        unscheduleGcIdler();
2426
2427        LoadedApk packageInfo = getPackageInfoNoCheck(
2428                data.info.applicationInfo, data.compatInfo);
2429        Service service = null;
2430        try {
2431            java.lang.ClassLoader cl = packageInfo.getClassLoader();
2432            service = (Service) cl.loadClass(data.info.name).newInstance();
2433        } catch (Exception e) {
2434            if (!mInstrumentation.onException(service, e)) {
2435                throw new RuntimeException(
2436                    "Unable to instantiate service " + data.info.name
2437                    + ": " + e.toString(), e);
2438            }
2439        }
2440
2441        try {
2442            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
2443
2444            ContextImpl context = new ContextImpl();
2445            context.init(packageInfo, null, this);
2446
2447            Application app = packageInfo.makeApplication(false, mInstrumentation);
2448            context.setOuterContext(service);
2449            service.attach(context, this, data.info.name, data.token, app,
2450                    ActivityManagerNative.getDefault());
2451            service.onCreate();
2452            mServices.put(data.token, service);
2453            try {
2454                ActivityManagerNative.getDefault().serviceDoneExecuting(
2455                        data.token, 0, 0, 0);
2456            } catch (RemoteException e) {
2457                // nothing to do.
2458            }
2459        } catch (Exception e) {
2460            if (!mInstrumentation.onException(service, e)) {
2461                throw new RuntimeException(
2462                    "Unable to create service " + data.info.name
2463                    + ": " + e.toString(), e);
2464            }
2465        }
2466    }
2467
2468    private void handleBindService(BindServiceData data) {
2469        Service s = mServices.get(data.token);
2470        if (DEBUG_SERVICE)
2471            Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
2472        if (s != null) {
2473            try {
2474                data.intent.setExtrasClassLoader(s.getClassLoader());
2475                try {
2476                    if (!data.rebind) {
2477                        IBinder binder = s.onBind(data.intent);
2478                        ActivityManagerNative.getDefault().publishService(
2479                                data.token, data.intent, binder);
2480                    } else {
2481                        s.onRebind(data.intent);
2482                        ActivityManagerNative.getDefault().serviceDoneExecuting(
2483                                data.token, 0, 0, 0);
2484                    }
2485                    ensureJitEnabled();
2486                } catch (RemoteException ex) {
2487                }
2488            } catch (Exception e) {
2489                if (!mInstrumentation.onException(s, e)) {
2490                    throw new RuntimeException(
2491                            "Unable to bind to service " + s
2492                            + " with " + data.intent + ": " + e.toString(), e);
2493                }
2494            }
2495        }
2496    }
2497
2498    private void handleUnbindService(BindServiceData data) {
2499        Service s = mServices.get(data.token);
2500        if (s != null) {
2501            try {
2502                data.intent.setExtrasClassLoader(s.getClassLoader());
2503                boolean doRebind = s.onUnbind(data.intent);
2504                try {
2505                    if (doRebind) {
2506                        ActivityManagerNative.getDefault().unbindFinished(
2507                                data.token, data.intent, doRebind);
2508                    } else {
2509                        ActivityManagerNative.getDefault().serviceDoneExecuting(
2510                                data.token, 0, 0, 0);
2511                    }
2512                } catch (RemoteException ex) {
2513                }
2514            } catch (Exception e) {
2515                if (!mInstrumentation.onException(s, e)) {
2516                    throw new RuntimeException(
2517                            "Unable to unbind to service " + s
2518                            + " with " + data.intent + ": " + e.toString(), e);
2519                }
2520            }
2521        }
2522    }
2523
2524    private void handleDumpService(DumpComponentInfo info) {
2525        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
2526        try {
2527            Service s = mServices.get(info.token);
2528            if (s != null) {
2529                PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
2530                s.dump(info.fd.getFileDescriptor(), pw, info.args);
2531                pw.flush();
2532            }
2533        } finally {
2534            IoUtils.closeQuietly(info.fd);
2535            StrictMode.setThreadPolicy(oldPolicy);
2536        }
2537    }
2538
2539    private void handleDumpActivity(DumpComponentInfo info) {
2540        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
2541        try {
2542            ActivityClientRecord r = mActivities.get(info.token);
2543            if (r != null && r.activity != null) {
2544                PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
2545                r.activity.dump(info.prefix, info.fd.getFileDescriptor(), pw, info.args);
2546                pw.flush();
2547            }
2548        } finally {
2549            IoUtils.closeQuietly(info.fd);
2550            StrictMode.setThreadPolicy(oldPolicy);
2551        }
2552    }
2553
2554    private void handleDumpProvider(DumpComponentInfo info) {
2555        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
2556        try {
2557            ProviderClientRecord r = mLocalProviders.get(info.token);
2558            if (r != null && r.mLocalProvider != null) {
2559                PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
2560                r.mLocalProvider.dump(info.fd.getFileDescriptor(), pw, info.args);
2561                pw.flush();
2562            }
2563        } finally {
2564            IoUtils.closeQuietly(info.fd);
2565            StrictMode.setThreadPolicy(oldPolicy);
2566        }
2567    }
2568
2569    private void handleServiceArgs(ServiceArgsData data) {
2570        Service s = mServices.get(data.token);
2571        if (s != null) {
2572            try {
2573                if (data.args != null) {
2574                    data.args.setExtrasClassLoader(s.getClassLoader());
2575                }
2576                int res;
2577                if (!data.taskRemoved) {
2578                    res = s.onStartCommand(data.args, data.flags, data.startId);
2579                } else {
2580                    s.onTaskRemoved(data.args);
2581                    res = Service.START_TASK_REMOVED_COMPLETE;
2582                }
2583
2584                QueuedWork.waitToFinish();
2585
2586                try {
2587                    ActivityManagerNative.getDefault().serviceDoneExecuting(
2588                            data.token, 1, data.startId, res);
2589                } catch (RemoteException e) {
2590                    // nothing to do.
2591                }
2592                ensureJitEnabled();
2593            } catch (Exception e) {
2594                if (!mInstrumentation.onException(s, e)) {
2595                    throw new RuntimeException(
2596                            "Unable to start service " + s
2597                            + " with " + data.args + ": " + e.toString(), e);
2598                }
2599            }
2600        }
2601    }
2602
2603    private void handleStopService(IBinder token) {
2604        Service s = mServices.remove(token);
2605        if (s != null) {
2606            try {
2607                if (localLOGV) Slog.v(TAG, "Destroying service " + s);
2608                s.onDestroy();
2609                Context context = s.getBaseContext();
2610                if (context instanceof ContextImpl) {
2611                    final String who = s.getClassName();
2612                    ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
2613                }
2614
2615                QueuedWork.waitToFinish();
2616
2617                try {
2618                    ActivityManagerNative.getDefault().serviceDoneExecuting(
2619                            token, 0, 0, 0);
2620                } catch (RemoteException e) {
2621                    // nothing to do.
2622                }
2623            } catch (Exception e) {
2624                if (!mInstrumentation.onException(s, e)) {
2625                    throw new RuntimeException(
2626                            "Unable to stop service " + s
2627                            + ": " + e.toString(), e);
2628                }
2629            }
2630        }
2631        //Slog.i(TAG, "Running services: " + mServices);
2632    }
2633
2634    public final ActivityClientRecord performResumeActivity(IBinder token,
2635            boolean clearHide) {
2636        ActivityClientRecord r = mActivities.get(token);
2637        if (localLOGV) Slog.v(TAG, "Performing resume of " + r
2638                + " finished=" + r.activity.mFinished);
2639        if (r != null && !r.activity.mFinished) {
2640            if (clearHide) {
2641                r.hideForNow = false;
2642                r.activity.mStartedActivity = false;
2643            }
2644            try {
2645                if (r.pendingIntents != null) {
2646                    deliverNewIntents(r, r.pendingIntents);
2647                    r.pendingIntents = null;
2648                }
2649                if (r.pendingResults != null) {
2650                    deliverResults(r, r.pendingResults);
2651                    r.pendingResults = null;
2652                }
2653                r.activity.performResume();
2654
2655                EventLog.writeEvent(LOG_ON_RESUME_CALLED,
2656                        r.activity.getComponentName().getClassName());
2657
2658                r.paused = false;
2659                r.stopped = false;
2660                r.state = null;
2661            } catch (Exception e) {
2662                if (!mInstrumentation.onException(r.activity, e)) {
2663                    throw new RuntimeException(
2664                        "Unable to resume activity "
2665                        + r.intent.getComponent().toShortString()
2666                        + ": " + e.toString(), e);
2667                }
2668            }
2669        }
2670        return r;
2671    }
2672
2673    static final void cleanUpPendingRemoveWindows(ActivityClientRecord r) {
2674        if (r.mPendingRemoveWindow != null) {
2675            r.mPendingRemoveWindowManager.removeViewImmediate(r.mPendingRemoveWindow);
2676            IBinder wtoken = r.mPendingRemoveWindow.getWindowToken();
2677            if (wtoken != null) {
2678                WindowManagerGlobal.getInstance().closeAll(wtoken,
2679                        r.activity.getClass().getName(), "Activity");
2680            }
2681        }
2682        r.mPendingRemoveWindow = null;
2683        r.mPendingRemoveWindowManager = null;
2684    }
2685
2686    final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
2687        // If we are getting ready to gc after going to the background, well
2688        // we are back active so skip it.
2689        unscheduleGcIdler();
2690
2691        ActivityClientRecord r = performResumeActivity(token, clearHide);
2692
2693        if (r != null) {
2694            final Activity a = r.activity;
2695
2696            if (localLOGV) Slog.v(
2697                TAG, "Resume " + r + " started activity: " +
2698                a.mStartedActivity + ", hideForNow: " + r.hideForNow
2699                + ", finished: " + a.mFinished);
2700
2701            final int forwardBit = isForward ?
2702                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
2703
2704            // If the window hasn't yet been added to the window manager,
2705            // and this guy didn't finish itself or start another activity,
2706            // then go ahead and add the window.
2707            boolean willBeVisible = !a.mStartedActivity;
2708            if (!willBeVisible) {
2709                try {
2710                    willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
2711                            a.getActivityToken());
2712                } catch (RemoteException e) {
2713                }
2714            }
2715            if (r.window == null && !a.mFinished && willBeVisible) {
2716                r.window = r.activity.getWindow();
2717                View decor = r.window.getDecorView();
2718                decor.setVisibility(View.INVISIBLE);
2719                ViewManager wm = a.getWindowManager();
2720                WindowManager.LayoutParams l = r.window.getAttributes();
2721                a.mDecor = decor;
2722                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
2723                l.softInputMode |= forwardBit;
2724                if (a.mVisibleFromClient) {
2725                    a.mWindowAdded = true;
2726                    wm.addView(decor, l);
2727                }
2728
2729            // If the window has already been added, but during resume
2730            // we started another activity, then don't yet make the
2731            // window visible.
2732            } else if (!willBeVisible) {
2733                if (localLOGV) Slog.v(
2734                    TAG, "Launch " + r + " mStartedActivity set");
2735                r.hideForNow = true;
2736            }
2737
2738            // Get rid of anything left hanging around.
2739            cleanUpPendingRemoveWindows(r);
2740
2741            // The window is now visible if it has been added, we are not
2742            // simply finishing, and we are not starting another activity.
2743            if (!r.activity.mFinished && willBeVisible
2744                    && r.activity.mDecor != null && !r.hideForNow) {
2745                if (r.newConfig != null) {
2746                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
2747                            + r.activityInfo.name + " with newConfig " + r.newConfig);
2748                    performConfigurationChanged(r.activity, r.newConfig);
2749                    freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.newConfig));
2750                    r.newConfig = null;
2751                }
2752                if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
2753                        + isForward);
2754                WindowManager.LayoutParams l = r.window.getAttributes();
2755                if ((l.softInputMode
2756                        & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
2757                        != forwardBit) {
2758                    l.softInputMode = (l.softInputMode
2759                            & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
2760                            | forwardBit;
2761                    if (r.activity.mVisibleFromClient) {
2762                        ViewManager wm = a.getWindowManager();
2763                        View decor = r.window.getDecorView();
2764                        wm.updateViewLayout(decor, l);
2765                    }
2766                }
2767                r.activity.mVisibleFromServer = true;
2768                mNumVisibleActivities++;
2769                if (r.activity.mVisibleFromClient) {
2770                    r.activity.makeVisible();
2771                }
2772            }
2773
2774            if (!r.onlyLocalRequest) {
2775                r.nextIdle = mNewActivities;
2776                mNewActivities = r;
2777                if (localLOGV) Slog.v(
2778                    TAG, "Scheduling idle handler for " + r);
2779                Looper.myQueue().addIdleHandler(new Idler());
2780            }
2781            r.onlyLocalRequest = false;
2782
2783        } else {
2784            // If an exception was thrown when trying to resume, then
2785            // just end this activity.
2786            try {
2787                ActivityManagerNative.getDefault()
2788                    .finishActivity(token, Activity.RESULT_CANCELED, null);
2789            } catch (RemoteException ex) {
2790            }
2791        }
2792    }
2793
2794    private int mThumbnailWidth = -1;
2795    private int mThumbnailHeight = -1;
2796    private Bitmap mAvailThumbnailBitmap = null;
2797    private Canvas mThumbnailCanvas = null;
2798
2799    private Bitmap createThumbnailBitmap(ActivityClientRecord r) {
2800        Bitmap thumbnail = mAvailThumbnailBitmap;
2801        try {
2802            if (thumbnail == null) {
2803                int w = mThumbnailWidth;
2804                int h;
2805                if (w < 0) {
2806                    Resources res = r.activity.getResources();
2807                    mThumbnailHeight = h =
2808                        res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
2809
2810                    mThumbnailWidth = w =
2811                        res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
2812                } else {
2813                    h = mThumbnailHeight;
2814                }
2815
2816                // On platforms where we don't want thumbnails, set dims to (0,0)
2817                if ((w > 0) && (h > 0)) {
2818                    thumbnail = Bitmap.createBitmap(r.activity.getResources().getDisplayMetrics(),
2819                            w, h, THUMBNAIL_FORMAT);
2820                    thumbnail.eraseColor(0);
2821                }
2822            }
2823
2824            if (thumbnail != null) {
2825                Canvas cv = mThumbnailCanvas;
2826                if (cv == null) {
2827                    mThumbnailCanvas = cv = new Canvas();
2828                }
2829
2830                cv.setBitmap(thumbnail);
2831                if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
2832                    mAvailThumbnailBitmap = thumbnail;
2833                    thumbnail = null;
2834                }
2835                cv.setBitmap(null);
2836            }
2837
2838        } catch (Exception e) {
2839            if (!mInstrumentation.onException(r.activity, e)) {
2840                throw new RuntimeException(
2841                        "Unable to create thumbnail of "
2842                        + r.intent.getComponent().toShortString()
2843                        + ": " + e.toString(), e);
2844            }
2845            thumbnail = null;
2846        }
2847
2848        return thumbnail;
2849    }
2850
2851    private void handlePauseActivity(IBinder token, boolean finished,
2852            boolean userLeaving, int configChanges) {
2853        ActivityClientRecord r = mActivities.get(token);
2854        if (r != null) {
2855            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
2856            if (userLeaving) {
2857                performUserLeavingActivity(r);
2858            }
2859
2860            r.activity.mConfigChangeFlags |= configChanges;
2861            performPauseActivity(token, finished, r.isPreHoneycomb());
2862
2863            // Make sure any pending writes are now committed.
2864            if (r.isPreHoneycomb()) {
2865                QueuedWork.waitToFinish();
2866            }
2867
2868            // Tell the activity manager we have paused.
2869            try {
2870                ActivityManagerNative.getDefault().activityPaused(token);
2871            } catch (RemoteException ex) {
2872            }
2873        }
2874    }
2875
2876    final void performUserLeavingActivity(ActivityClientRecord r) {
2877        mInstrumentation.callActivityOnUserLeaving(r.activity);
2878    }
2879
2880    final Bundle performPauseActivity(IBinder token, boolean finished,
2881            boolean saveState) {
2882        ActivityClientRecord r = mActivities.get(token);
2883        return r != null ? performPauseActivity(r, finished, saveState) : null;
2884    }
2885
2886    final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
2887            boolean saveState) {
2888        if (r.paused) {
2889            if (r.activity.mFinished) {
2890                // If we are finishing, we won't call onResume() in certain cases.
2891                // So here we likewise don't want to call onPause() if the activity
2892                // isn't resumed.
2893                return null;
2894            }
2895            RuntimeException e = new RuntimeException(
2896                    "Performing pause of activity that is not resumed: "
2897                    + r.intent.getComponent().toShortString());
2898            Slog.e(TAG, e.getMessage(), e);
2899        }
2900        Bundle state = null;
2901        if (finished) {
2902            r.activity.mFinished = true;
2903        }
2904        try {
2905            // Next have the activity save its current state and managed dialogs...
2906            if (!r.activity.mFinished && saveState) {
2907                state = new Bundle();
2908                state.setAllowFds(false);
2909                mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
2910                r.state = state;
2911            }
2912            // Now we are idle.
2913            r.activity.mCalled = false;
2914            mInstrumentation.callActivityOnPause(r.activity);
2915            EventLog.writeEvent(LOG_ON_PAUSE_CALLED, r.activity.getComponentName().getClassName());
2916            if (!r.activity.mCalled) {
2917                throw new SuperNotCalledException(
2918                    "Activity " + r.intent.getComponent().toShortString() +
2919                    " did not call through to super.onPause()");
2920            }
2921
2922        } catch (SuperNotCalledException e) {
2923            throw e;
2924
2925        } catch (Exception e) {
2926            if (!mInstrumentation.onException(r.activity, e)) {
2927                throw new RuntimeException(
2928                        "Unable to pause activity "
2929                        + r.intent.getComponent().toShortString()
2930                        + ": " + e.toString(), e);
2931            }
2932        }
2933        r.paused = true;
2934
2935        // Notify any outstanding on paused listeners
2936        ArrayList<OnActivityPausedListener> listeners;
2937        synchronized (mOnPauseListeners) {
2938            listeners = mOnPauseListeners.remove(r.activity);
2939        }
2940        int size = (listeners != null ? listeners.size() : 0);
2941        for (int i = 0; i < size; i++) {
2942            listeners.get(i).onPaused(r.activity);
2943        }
2944
2945        return state;
2946    }
2947
2948    final void performStopActivity(IBinder token, boolean saveState) {
2949        ActivityClientRecord r = mActivities.get(token);
2950        performStopActivityInner(r, null, false, saveState);
2951    }
2952
2953    private static class StopInfo implements Runnable {
2954        ActivityClientRecord activity;
2955        Bundle state;
2956        Bitmap thumbnail;
2957        CharSequence description;
2958
2959        @Override public void run() {
2960            // Tell activity manager we have been stopped.
2961            try {
2962                if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Reporting activity stopped: " + activity);
2963                ActivityManagerNative.getDefault().activityStopped(
2964                    activity.token, state, thumbnail, description);
2965            } catch (RemoteException ex) {
2966            }
2967        }
2968    }
2969
2970    private static final class ProviderRefCount {
2971        public final IActivityManager.ContentProviderHolder holder;
2972        public final ProviderClientRecord client;
2973        public int stableCount;
2974        public int unstableCount;
2975
2976        // When this is set, the stable and unstable ref counts are 0 and
2977        // we have a pending operation scheduled to remove the ref count
2978        // from the activity manager.  On the activity manager we are still
2979        // holding an unstable ref, though it is not reflected in the counts
2980        // here.
2981        public boolean removePending;
2982
2983        ProviderRefCount(IActivityManager.ContentProviderHolder inHolder,
2984                ProviderClientRecord inClient, int sCount, int uCount) {
2985            holder = inHolder;
2986            client = inClient;
2987            stableCount = sCount;
2988            unstableCount = uCount;
2989        }
2990    }
2991
2992    /**
2993     * Core implementation of stopping an activity.  Note this is a little
2994     * tricky because the server's meaning of stop is slightly different
2995     * than our client -- for the server, stop means to save state and give
2996     * it the result when it is done, but the window may still be visible.
2997     * For the client, we want to call onStop()/onStart() to indicate when
2998     * the activity's UI visibillity changes.
2999     */
3000    private void performStopActivityInner(ActivityClientRecord r,
3001            StopInfo info, boolean keepShown, boolean saveState) {
3002        if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
3003        Bundle state = null;
3004        if (r != null) {
3005            if (!keepShown && r.stopped) {
3006                if (r.activity.mFinished) {
3007                    // If we are finishing, we won't call onResume() in certain
3008                    // cases.  So here we likewise don't want to call onStop()
3009                    // if the activity isn't resumed.
3010                    return;
3011                }
3012                RuntimeException e = new RuntimeException(
3013                        "Performing stop of activity that is not resumed: "
3014                        + r.intent.getComponent().toShortString());
3015                Slog.e(TAG, e.getMessage(), e);
3016            }
3017
3018            if (info != null) {
3019                try {
3020                    // First create a thumbnail for the activity...
3021                    // For now, don't create the thumbnail here; we are
3022                    // doing that by doing a screen snapshot.
3023                    info.thumbnail = null; //createThumbnailBitmap(r);
3024                    info.description = r.activity.onCreateDescription();
3025                } catch (Exception e) {
3026                    if (!mInstrumentation.onException(r.activity, e)) {
3027                        throw new RuntimeException(
3028                                "Unable to save state of activity "
3029                                + r.intent.getComponent().toShortString()
3030                                + ": " + e.toString(), e);
3031                    }
3032                }
3033            }
3034
3035            // Next have the activity save its current state and managed dialogs...
3036            if (!r.activity.mFinished && saveState) {
3037                if (r.state == null) {
3038                    state = new Bundle();
3039                    state.setAllowFds(false);
3040                    mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
3041                    r.state = state;
3042                } else {
3043                    state = r.state;
3044                }
3045            }
3046
3047            if (!keepShown) {
3048                try {
3049                    // Now we are idle.
3050                    r.activity.performStop();
3051                } catch (Exception e) {
3052                    if (!mInstrumentation.onException(r.activity, e)) {
3053                        throw new RuntimeException(
3054                                "Unable to stop activity "
3055                                + r.intent.getComponent().toShortString()
3056                                + ": " + e.toString(), e);
3057                    }
3058                }
3059                r.stopped = true;
3060            }
3061
3062            r.paused = true;
3063        }
3064    }
3065
3066    private void updateVisibility(ActivityClientRecord r, boolean show) {
3067        View v = r.activity.mDecor;
3068        if (v != null) {
3069            if (show) {
3070                if (!r.activity.mVisibleFromServer) {
3071                    r.activity.mVisibleFromServer = true;
3072                    mNumVisibleActivities++;
3073                    if (r.activity.mVisibleFromClient) {
3074                        r.activity.makeVisible();
3075                    }
3076                }
3077                if (r.newConfig != null) {
3078                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
3079                            + r.activityInfo.name + " with new config " + r.newConfig);
3080                    performConfigurationChanged(r.activity, r.newConfig);
3081                    freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.newConfig));
3082                    r.newConfig = null;
3083                }
3084            } else {
3085                if (r.activity.mVisibleFromServer) {
3086                    r.activity.mVisibleFromServer = false;
3087                    mNumVisibleActivities--;
3088                    v.setVisibility(View.INVISIBLE);
3089                }
3090            }
3091        }
3092    }
3093
3094    private void handleStopActivity(IBinder token, boolean show, int configChanges) {
3095        ActivityClientRecord r = mActivities.get(token);
3096        r.activity.mConfigChangeFlags |= configChanges;
3097
3098        StopInfo info = new StopInfo();
3099        performStopActivityInner(r, info, show, true);
3100
3101        if (localLOGV) Slog.v(
3102            TAG, "Finishing stop of " + r + ": show=" + show
3103            + " win=" + r.window);
3104
3105        updateVisibility(r, show);
3106
3107        // Make sure any pending writes are now committed.
3108        if (!r.isPreHoneycomb()) {
3109            QueuedWork.waitToFinish();
3110        }
3111
3112        // Schedule the call to tell the activity manager we have
3113        // stopped.  We don't do this immediately, because we want to
3114        // have a chance for any other pending work (in particular memory
3115        // trim requests) to complete before you tell the activity
3116        // manager to proceed and allow us to go fully into the background.
3117        info.activity = r;
3118        info.state = r.state;
3119        mH.post(info);
3120    }
3121
3122    final void performRestartActivity(IBinder token) {
3123        ActivityClientRecord r = mActivities.get(token);
3124        if (r.stopped) {
3125            r.activity.performRestart();
3126            r.stopped = false;
3127        }
3128    }
3129
3130    private void handleWindowVisibility(IBinder token, boolean show) {
3131        ActivityClientRecord r = mActivities.get(token);
3132
3133        if (r == null) {
3134            Log.w(TAG, "handleWindowVisibility: no activity for token " + token);
3135            return;
3136        }
3137
3138        if (!show && !r.stopped) {
3139            performStopActivityInner(r, null, show, false);
3140        } else if (show && r.stopped) {
3141            // If we are getting ready to gc after going to the background, well
3142            // we are back active so skip it.
3143            unscheduleGcIdler();
3144
3145            r.activity.performRestart();
3146            r.stopped = false;
3147        }
3148        if (r.activity.mDecor != null) {
3149            if (false) Slog.v(
3150                TAG, "Handle window " + r + " visibility: " + show);
3151            updateVisibility(r, show);
3152        }
3153    }
3154
3155    private void handleSleeping(IBinder token, boolean sleeping) {
3156        ActivityClientRecord r = mActivities.get(token);
3157
3158        if (r == null) {
3159            Log.w(TAG, "handleSleeping: no activity for token " + token);
3160            return;
3161        }
3162
3163        if (sleeping) {
3164            if (!r.stopped && !r.isPreHoneycomb()) {
3165                try {
3166                    // Now we are idle.
3167                    r.activity.performStop();
3168                } catch (Exception e) {
3169                    if (!mInstrumentation.onException(r.activity, e)) {
3170                        throw new RuntimeException(
3171                                "Unable to stop activity "
3172                                + r.intent.getComponent().toShortString()
3173                                + ": " + e.toString(), e);
3174                    }
3175                }
3176                r.stopped = true;
3177            }
3178
3179            // Make sure any pending writes are now committed.
3180            if (!r.isPreHoneycomb()) {
3181                QueuedWork.waitToFinish();
3182            }
3183
3184            // Tell activity manager we slept.
3185            try {
3186                ActivityManagerNative.getDefault().activitySlept(r.token);
3187            } catch (RemoteException ex) {
3188            }
3189        } else {
3190            if (r.stopped && r.activity.mVisibleFromServer) {
3191                r.activity.performRestart();
3192                r.stopped = false;
3193            }
3194        }
3195    }
3196
3197    private void handleSetCoreSettings(Bundle coreSettings) {
3198        synchronized (mPackages) {
3199            mCoreSettings = coreSettings;
3200        }
3201    }
3202
3203    private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) {
3204        LoadedApk apk = peekPackageInfo(data.pkg, false);
3205        if (apk != null) {
3206            apk.mCompatibilityInfo.set(data.info);
3207        }
3208        apk = peekPackageInfo(data.pkg, true);
3209        if (apk != null) {
3210            apk.mCompatibilityInfo.set(data.info);
3211        }
3212        handleConfigurationChanged(mConfiguration, data.info);
3213        WindowManagerGlobal.getInstance().reportNewConfiguration(mConfiguration);
3214    }
3215
3216    private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
3217        final int N = results.size();
3218        for (int i=0; i<N; i++) {
3219            ResultInfo ri = results.get(i);
3220            try {
3221                if (ri.mData != null) {
3222                    ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
3223                }
3224                if (DEBUG_RESULTS) Slog.v(TAG,
3225                        "Delivering result to activity " + r + " : " + ri);
3226                r.activity.dispatchActivityResult(ri.mResultWho,
3227                        ri.mRequestCode, ri.mResultCode, ri.mData);
3228            } catch (Exception e) {
3229                if (!mInstrumentation.onException(r.activity, e)) {
3230                    throw new RuntimeException(
3231                            "Failure delivering result " + ri + " to activity "
3232                            + r.intent.getComponent().toShortString()
3233                            + ": " + e.toString(), e);
3234                }
3235            }
3236        }
3237    }
3238
3239    private void handleSendResult(ResultData res) {
3240        ActivityClientRecord r = mActivities.get(res.token);
3241        if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
3242        if (r != null) {
3243            final boolean resumed = !r.paused;
3244            if (!r.activity.mFinished && r.activity.mDecor != null
3245                    && r.hideForNow && resumed) {
3246                // We had hidden the activity because it started another
3247                // one...  we have gotten a result back and we are not
3248                // paused, so make sure our window is visible.
3249                updateVisibility(r, true);
3250            }
3251            if (resumed) {
3252                try {
3253                    // Now we are idle.
3254                    r.activity.mCalled = false;
3255                    r.activity.mTemporaryPause = true;
3256                    mInstrumentation.callActivityOnPause(r.activity);
3257                    if (!r.activity.mCalled) {
3258                        throw new SuperNotCalledException(
3259                            "Activity " + r.intent.getComponent().toShortString()
3260                            + " did not call through to super.onPause()");
3261                    }
3262                } catch (SuperNotCalledException e) {
3263                    throw e;
3264                } catch (Exception e) {
3265                    if (!mInstrumentation.onException(r.activity, e)) {
3266                        throw new RuntimeException(
3267                                "Unable to pause activity "
3268                                + r.intent.getComponent().toShortString()
3269                                + ": " + e.toString(), e);
3270                    }
3271                }
3272            }
3273            deliverResults(r, res.results);
3274            if (resumed) {
3275                r.activity.performResume();
3276                r.activity.mTemporaryPause = false;
3277            }
3278        }
3279    }
3280
3281    public final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing) {
3282        return performDestroyActivity(token, finishing, 0, false);
3283    }
3284
3285    private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
3286            int configChanges, boolean getNonConfigInstance) {
3287        ActivityClientRecord r = mActivities.get(token);
3288        Class activityClass = null;
3289        if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
3290        if (r != null) {
3291            activityClass = r.activity.getClass();
3292            r.activity.mConfigChangeFlags |= configChanges;
3293            if (finishing) {
3294                r.activity.mFinished = true;
3295            }
3296            if (!r.paused) {
3297                try {
3298                    r.activity.mCalled = false;
3299                    mInstrumentation.callActivityOnPause(r.activity);
3300                    EventLog.writeEvent(LOG_ON_PAUSE_CALLED,
3301                            r.activity.getComponentName().getClassName());
3302                    if (!r.activity.mCalled) {
3303                        throw new SuperNotCalledException(
3304                            "Activity " + safeToComponentShortString(r.intent)
3305                            + " did not call through to super.onPause()");
3306                    }
3307                } catch (SuperNotCalledException e) {
3308                    throw e;
3309                } catch (Exception e) {
3310                    if (!mInstrumentation.onException(r.activity, e)) {
3311                        throw new RuntimeException(
3312                                "Unable to pause activity "
3313                                + safeToComponentShortString(r.intent)
3314                                + ": " + e.toString(), e);
3315                    }
3316                }
3317                r.paused = true;
3318            }
3319            if (!r.stopped) {
3320                try {
3321                    r.activity.performStop();
3322                } catch (SuperNotCalledException e) {
3323                    throw e;
3324                } catch (Exception e) {
3325                    if (!mInstrumentation.onException(r.activity, e)) {
3326                        throw new RuntimeException(
3327                                "Unable to stop activity "
3328                                + safeToComponentShortString(r.intent)
3329                                + ": " + e.toString(), e);
3330                    }
3331                }
3332                r.stopped = true;
3333            }
3334            if (getNonConfigInstance) {
3335                try {
3336                    r.lastNonConfigurationInstances
3337                            = r.activity.retainNonConfigurationInstances();
3338                } catch (Exception e) {
3339                    if (!mInstrumentation.onException(r.activity, e)) {
3340                        throw new RuntimeException(
3341                                "Unable to retain activity "
3342                                + r.intent.getComponent().toShortString()
3343                                + ": " + e.toString(), e);
3344                    }
3345                }
3346            }
3347            try {
3348                r.activity.mCalled = false;
3349                mInstrumentation.callActivityOnDestroy(r.activity);
3350                if (!r.activity.mCalled) {
3351                    throw new SuperNotCalledException(
3352                        "Activity " + safeToComponentShortString(r.intent) +
3353                        " did not call through to super.onDestroy()");
3354                }
3355                if (r.window != null) {
3356                    r.window.closeAllPanels();
3357                }
3358            } catch (SuperNotCalledException e) {
3359                throw e;
3360            } catch (Exception e) {
3361                if (!mInstrumentation.onException(r.activity, e)) {
3362                    throw new RuntimeException(
3363                            "Unable to destroy activity " + safeToComponentShortString(r.intent)
3364                            + ": " + e.toString(), e);
3365                }
3366            }
3367        }
3368        mActivities.remove(token);
3369        StrictMode.decrementExpectedActivityCount(activityClass);
3370        return r;
3371    }
3372
3373    private static String safeToComponentShortString(Intent intent) {
3374        ComponentName component = intent.getComponent();
3375        return component == null ? "[Unknown]" : component.toShortString();
3376    }
3377
3378    private void handleDestroyActivity(IBinder token, boolean finishing,
3379            int configChanges, boolean getNonConfigInstance) {
3380        ActivityClientRecord r = performDestroyActivity(token, finishing,
3381                configChanges, getNonConfigInstance);
3382        if (r != null) {
3383            cleanUpPendingRemoveWindows(r);
3384            WindowManager wm = r.activity.getWindowManager();
3385            View v = r.activity.mDecor;
3386            if (v != null) {
3387                if (r.activity.mVisibleFromServer) {
3388                    mNumVisibleActivities--;
3389                }
3390                IBinder wtoken = v.getWindowToken();
3391                if (r.activity.mWindowAdded) {
3392                    if (r.onlyLocalRequest) {
3393                        // Hold off on removing this until the new activity's
3394                        // window is being added.
3395                        r.mPendingRemoveWindow = v;
3396                        r.mPendingRemoveWindowManager = wm;
3397                    } else {
3398                        wm.removeViewImmediate(v);
3399                    }
3400                }
3401                if (wtoken != null && r.mPendingRemoveWindow == null) {
3402                    WindowManagerGlobal.getInstance().closeAll(wtoken,
3403                            r.activity.getClass().getName(), "Activity");
3404                }
3405                r.activity.mDecor = null;
3406            }
3407            if (r.mPendingRemoveWindow == null) {
3408                // If we are delaying the removal of the activity window, then
3409                // we can't clean up all windows here.  Note that we can't do
3410                // so later either, which means any windows that aren't closed
3411                // by the app will leak.  Well we try to warning them a lot
3412                // about leaking windows, because that is a bug, so if they are
3413                // using this recreate facility then they get to live with leaks.
3414                WindowManagerGlobal.getInstance().closeAll(token,
3415                        r.activity.getClass().getName(), "Activity");
3416            }
3417
3418            // Mocked out contexts won't be participating in the normal
3419            // process lifecycle, but if we're running with a proper
3420            // ApplicationContext we need to have it tear down things
3421            // cleanly.
3422            Context c = r.activity.getBaseContext();
3423            if (c instanceof ContextImpl) {
3424                ((ContextImpl) c).scheduleFinalCleanup(
3425                        r.activity.getClass().getName(), "Activity");
3426            }
3427        }
3428        if (finishing) {
3429            try {
3430                ActivityManagerNative.getDefault().activityDestroyed(token);
3431            } catch (RemoteException ex) {
3432                // If the system process has died, it's game over for everyone.
3433            }
3434        }
3435    }
3436
3437    public final void requestRelaunchActivity(IBinder token,
3438            List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
3439            int configChanges, boolean notResumed, Configuration config,
3440            boolean fromServer) {
3441        ActivityClientRecord target = null;
3442
3443        synchronized (mPackages) {
3444            for (int i=0; i<mRelaunchingActivities.size(); i++) {
3445                ActivityClientRecord r = mRelaunchingActivities.get(i);
3446                if (r.token == token) {
3447                    target = r;
3448                    if (pendingResults != null) {
3449                        if (r.pendingResults != null) {
3450                            r.pendingResults.addAll(pendingResults);
3451                        } else {
3452                            r.pendingResults = pendingResults;
3453                        }
3454                    }
3455                    if (pendingNewIntents != null) {
3456                        if (r.pendingIntents != null) {
3457                            r.pendingIntents.addAll(pendingNewIntents);
3458                        } else {
3459                            r.pendingIntents = pendingNewIntents;
3460                        }
3461                    }
3462                    break;
3463                }
3464            }
3465
3466            if (target == null) {
3467                target = new ActivityClientRecord();
3468                target.token = token;
3469                target.pendingResults = pendingResults;
3470                target.pendingIntents = pendingNewIntents;
3471                if (!fromServer) {
3472                    ActivityClientRecord existing = mActivities.get(token);
3473                    if (existing != null) {
3474                        target.startsNotResumed = existing.paused;
3475                    }
3476                    target.onlyLocalRequest = true;
3477                }
3478                mRelaunchingActivities.add(target);
3479                queueOrSendMessage(H.RELAUNCH_ACTIVITY, target);
3480            }
3481
3482            if (fromServer) {
3483                target.startsNotResumed = notResumed;
3484                target.onlyLocalRequest = false;
3485            }
3486            if (config != null) {
3487                target.createdConfig = config;
3488            }
3489            target.pendingConfigChanges |= configChanges;
3490        }
3491    }
3492
3493    private void handleRelaunchActivity(ActivityClientRecord tmp) {
3494        // If we are getting ready to gc after going to the background, well
3495        // we are back active so skip it.
3496        unscheduleGcIdler();
3497
3498        Configuration changedConfig = null;
3499        int configChanges = 0;
3500
3501        // First: make sure we have the most recent configuration and most
3502        // recent version of the activity, or skip it if some previous call
3503        // had taken a more recent version.
3504        synchronized (mPackages) {
3505            int N = mRelaunchingActivities.size();
3506            IBinder token = tmp.token;
3507            tmp = null;
3508            for (int i=0; i<N; i++) {
3509                ActivityClientRecord r = mRelaunchingActivities.get(i);
3510                if (r.token == token) {
3511                    tmp = r;
3512                    configChanges |= tmp.pendingConfigChanges;
3513                    mRelaunchingActivities.remove(i);
3514                    i--;
3515                    N--;
3516                }
3517            }
3518
3519            if (tmp == null) {
3520                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Abort, activity not relaunching!");
3521                return;
3522            }
3523
3524            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
3525                    + tmp.token + " with configChanges=0x"
3526                    + Integer.toHexString(configChanges));
3527
3528            if (mPendingConfiguration != null) {
3529                changedConfig = mPendingConfiguration;
3530                mPendingConfiguration = null;
3531            }
3532        }
3533
3534        if (tmp.createdConfig != null) {
3535            // If the activity manager is passing us its current config,
3536            // assume that is really what we want regardless of what we
3537            // may have pending.
3538            if (mConfiguration == null
3539                    || (tmp.createdConfig.isOtherSeqNewer(mConfiguration)
3540                            && mConfiguration.diff(tmp.createdConfig) != 0)) {
3541                if (changedConfig == null
3542                        || tmp.createdConfig.isOtherSeqNewer(changedConfig)) {
3543                    changedConfig = tmp.createdConfig;
3544                }
3545            }
3546        }
3547
3548        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
3549                + tmp.token + ": changedConfig=" + changedConfig);
3550
3551        // If there was a pending configuration change, execute it first.
3552        if (changedConfig != null) {
3553            mCurDefaultDisplayDpi = changedConfig.densityDpi;
3554            updateDefaultDensity();
3555            handleConfigurationChanged(changedConfig, null);
3556        }
3557
3558        ActivityClientRecord r = mActivities.get(tmp.token);
3559        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r);
3560        if (r == null) {
3561            return;
3562        }
3563
3564        r.activity.mConfigChangeFlags |= configChanges;
3565        r.onlyLocalRequest = tmp.onlyLocalRequest;
3566        Intent currentIntent = r.activity.mIntent;
3567
3568        r.activity.mChangingConfigurations = true;
3569
3570        // Need to ensure state is saved.
3571        if (!r.paused) {
3572            performPauseActivity(r.token, false, r.isPreHoneycomb());
3573        }
3574        if (r.state == null && !r.stopped && !r.isPreHoneycomb()) {
3575            r.state = new Bundle();
3576            r.state.setAllowFds(false);
3577            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
3578        }
3579
3580        handleDestroyActivity(r.token, false, configChanges, true);
3581
3582        r.activity = null;
3583        r.window = null;
3584        r.hideForNow = false;
3585        r.nextIdle = null;
3586        // Merge any pending results and pending intents; don't just replace them
3587        if (tmp.pendingResults != null) {
3588            if (r.pendingResults == null) {
3589                r.pendingResults = tmp.pendingResults;
3590            } else {
3591                r.pendingResults.addAll(tmp.pendingResults);
3592            }
3593        }
3594        if (tmp.pendingIntents != null) {
3595            if (r.pendingIntents == null) {
3596                r.pendingIntents = tmp.pendingIntents;
3597            } else {
3598                r.pendingIntents.addAll(tmp.pendingIntents);
3599            }
3600        }
3601        r.startsNotResumed = tmp.startsNotResumed;
3602
3603        handleLaunchActivity(r, currentIntent);
3604    }
3605
3606    private void handleRequestThumbnail(IBinder token) {
3607        ActivityClientRecord r = mActivities.get(token);
3608        Bitmap thumbnail = createThumbnailBitmap(r);
3609        CharSequence description = null;
3610        try {
3611            description = r.activity.onCreateDescription();
3612        } catch (Exception e) {
3613            if (!mInstrumentation.onException(r.activity, e)) {
3614                throw new RuntimeException(
3615                        "Unable to create description of activity "
3616                        + r.intent.getComponent().toShortString()
3617                        + ": " + e.toString(), e);
3618            }
3619        }
3620        //System.out.println("Reporting top thumbnail " + thumbnail);
3621        try {
3622            ActivityManagerNative.getDefault().reportThumbnail(
3623                token, thumbnail, description);
3624        } catch (RemoteException ex) {
3625        }
3626    }
3627
3628    ArrayList<ComponentCallbacks2> collectComponentCallbacksLocked(
3629            boolean allActivities, Configuration newConfig) {
3630        ArrayList<ComponentCallbacks2> callbacks
3631                = new ArrayList<ComponentCallbacks2>();
3632
3633        if (mActivities.size() > 0) {
3634            for (ActivityClientRecord ar : mActivities.values()) {
3635                Activity a = ar.activity;
3636                if (a != null) {
3637                    Configuration thisConfig = applyConfigCompatMainThread(mCurDefaultDisplayDpi,
3638                            newConfig, ar.packageInfo.mCompatibilityInfo.getIfNeeded());
3639                    if (!ar.activity.mFinished && (allActivities || !ar.paused)) {
3640                        // If the activity is currently resumed, its configuration
3641                        // needs to change right now.
3642                        callbacks.add(a);
3643                    } else if (thisConfig != null) {
3644                        // Otherwise, we will tell it about the change
3645                        // the next time it is resumed or shown.  Note that
3646                        // the activity manager may, before then, decide the
3647                        // activity needs to be destroyed to handle its new
3648                        // configuration.
3649                        if (DEBUG_CONFIGURATION) {
3650                            Slog.v(TAG, "Setting activity "
3651                                    + ar.activityInfo.name + " newConfig=" + thisConfig);
3652                        }
3653                        ar.newConfig = thisConfig;
3654                    }
3655                }
3656            }
3657        }
3658        if (mServices.size() > 0) {
3659            for (Service service : mServices.values()) {
3660                callbacks.add(service);
3661            }
3662        }
3663        synchronized (mProviderMap) {
3664            if (mLocalProviders.size() > 0) {
3665                for (ProviderClientRecord providerClientRecord : mLocalProviders.values()) {
3666                    callbacks.add(providerClientRecord.mLocalProvider);
3667                }
3668            }
3669        }
3670        final int N = mAllApplications.size();
3671        for (int i=0; i<N; i++) {
3672            callbacks.add(mAllApplications.get(i));
3673        }
3674
3675        return callbacks;
3676    }
3677
3678    private static void performConfigurationChanged(ComponentCallbacks2 cb, Configuration config) {
3679        // Only for Activity objects, check that they actually call up to their
3680        // superclass implementation.  ComponentCallbacks2 is an interface, so
3681        // we check the runtime type and act accordingly.
3682        Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
3683        if (activity != null) {
3684            activity.mCalled = false;
3685        }
3686
3687        boolean shouldChangeConfig = false;
3688        if ((activity == null) || (activity.mCurrentConfig == null)) {
3689            shouldChangeConfig = true;
3690        } else {
3691
3692            // If the new config is the same as the config this Activity
3693            // is already running with then don't bother calling
3694            // onConfigurationChanged
3695            int diff = activity.mCurrentConfig.diff(config);
3696            if (diff != 0) {
3697                // If this activity doesn't handle any of the config changes
3698                // then don't bother calling onConfigurationChanged as we're
3699                // going to destroy it.
3700                if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0) {
3701                    shouldChangeConfig = true;
3702                }
3703            }
3704        }
3705
3706        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb
3707                + ": shouldChangeConfig=" + shouldChangeConfig);
3708        if (shouldChangeConfig) {
3709            cb.onConfigurationChanged(config);
3710
3711            if (activity != null) {
3712                if (!activity.mCalled) {
3713                    throw new SuperNotCalledException(
3714                            "Activity " + activity.getLocalClassName() +
3715                        " did not call through to super.onConfigurationChanged()");
3716                }
3717                activity.mConfigChangeFlags = 0;
3718                activity.mCurrentConfig = new Configuration(config);
3719            }
3720        }
3721    }
3722
3723    public final void applyConfigurationToResources(Configuration config) {
3724        synchronized (mPackages) {
3725            applyConfigurationToResourcesLocked(config, null);
3726        }
3727    }
3728
3729    final boolean applyConfigurationToResourcesLocked(Configuration config,
3730            CompatibilityInfo compat) {
3731        if (mResConfiguration == null) {
3732            mResConfiguration = new Configuration();
3733        }
3734        if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) {
3735            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
3736                    + mResConfiguration.seq + ", newSeq=" + config.seq);
3737            return false;
3738        }
3739        int changes = mResConfiguration.updateFrom(config);
3740        flushDisplayMetricsLocked();
3741        DisplayMetrics defaultDisplayMetrics = getDisplayMetricsLocked(
3742                Display.DEFAULT_DISPLAY, null);
3743
3744        if (compat != null && (mResCompatibilityInfo == null ||
3745                !mResCompatibilityInfo.equals(compat))) {
3746            mResCompatibilityInfo = compat;
3747            changes |= ActivityInfo.CONFIG_SCREEN_LAYOUT
3748                    | ActivityInfo.CONFIG_SCREEN_SIZE
3749                    | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
3750        }
3751
3752        // set it for java, this also affects newly created Resources
3753        if (config.locale != null) {
3754            Locale.setDefault(config.locale);
3755        }
3756
3757        Resources.updateSystemConfiguration(config, defaultDisplayMetrics, compat);
3758
3759        ApplicationPackageManager.configurationChanged();
3760        //Slog.i(TAG, "Configuration changed in " + currentPackageName());
3761
3762        Configuration tmpConfig = null;
3763
3764        Iterator<Map.Entry<ResourcesKey, WeakReference<Resources>>> it =
3765                mActiveResources.entrySet().iterator();
3766        while (it.hasNext()) {
3767            Map.Entry<ResourcesKey, WeakReference<Resources>> entry = it.next();
3768            Resources r = entry.getValue().get();
3769            if (r != null) {
3770                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
3771                        + r + " config to: " + config);
3772                int displayId = entry.getKey().mDisplayId;
3773                boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
3774                DisplayMetrics dm = defaultDisplayMetrics;
3775                Configuration overrideConfig = entry.getKey().mOverrideConfiguration;
3776                if (!isDefaultDisplay || overrideConfig != null) {
3777                    if (tmpConfig == null) {
3778                        tmpConfig = new Configuration();
3779                    }
3780                    tmpConfig.setTo(config);
3781                    if (!isDefaultDisplay) {
3782                        dm = getDisplayMetricsLocked(displayId, null);
3783                        applyNonDefaultDisplayMetricsToConfigurationLocked(dm, tmpConfig);
3784                    }
3785                    if (overrideConfig != null) {
3786                        tmpConfig.updateFrom(overrideConfig);
3787                    }
3788                    r.updateConfiguration(tmpConfig, dm, compat);
3789                } else {
3790                    r.updateConfiguration(config, dm, compat);
3791                }
3792                //Slog.i(TAG, "Updated app resources " + v.getKey()
3793                //        + " " + r + ": " + r.getConfiguration());
3794            } else {
3795                //Slog.i(TAG, "Removing old resources " + v.getKey());
3796                it.remove();
3797            }
3798        }
3799
3800        return changes != 0;
3801    }
3802
3803    final void applyNonDefaultDisplayMetricsToConfigurationLocked(
3804            DisplayMetrics dm, Configuration config) {
3805        config.screenLayout = Configuration.SCREENLAYOUT_SIZE_XLARGE
3806                | Configuration.SCREENLAYOUT_LONG_NO;
3807        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
3808        config.orientation = (dm.widthPixels >= dm.heightPixels) ?
3809                Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT;
3810        config.densityDpi = dm.densityDpi;
3811        config.screenWidthDp = (int)(dm.widthPixels / dm.density);
3812        config.screenHeightDp = (int)(dm.heightPixels / dm.density);
3813        config.smallestScreenWidthDp = config.screenWidthDp; // assume screen does not rotate
3814        config.compatScreenWidthDp = config.screenWidthDp;
3815        config.compatScreenHeightDp = config.screenHeightDp;
3816        config.compatSmallestScreenWidthDp = config.smallestScreenWidthDp;
3817    }
3818
3819    final Configuration applyCompatConfiguration(int displayDensity) {
3820        Configuration config = mConfiguration;
3821        if (mCompatConfiguration == null) {
3822            mCompatConfiguration = new Configuration();
3823        }
3824        mCompatConfiguration.setTo(mConfiguration);
3825        if (mResCompatibilityInfo != null && !mResCompatibilityInfo.supportsScreen()) {
3826            mResCompatibilityInfo.applyToConfiguration(displayDensity, mCompatConfiguration);
3827            config = mCompatConfiguration;
3828        }
3829        return config;
3830    }
3831
3832    final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {
3833
3834        ArrayList<ComponentCallbacks2> callbacks = null;
3835        int configDiff = 0;
3836
3837        synchronized (mPackages) {
3838            if (mPendingConfiguration != null) {
3839                if (!mPendingConfiguration.isOtherSeqNewer(config)) {
3840                    config = mPendingConfiguration;
3841                    mCurDefaultDisplayDpi = config.densityDpi;
3842                    updateDefaultDensity();
3843                }
3844                mPendingConfiguration = null;
3845            }
3846
3847            if (config == null) {
3848                return;
3849            }
3850
3851            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: "
3852                    + config);
3853
3854            applyConfigurationToResourcesLocked(config, compat);
3855
3856            if (mConfiguration == null) {
3857                mConfiguration = new Configuration();
3858            }
3859            if (!mConfiguration.isOtherSeqNewer(config) && compat == null) {
3860                return;
3861            }
3862            configDiff = mConfiguration.diff(config);
3863            mConfiguration.updateFrom(config);
3864            config = applyCompatConfiguration(mCurDefaultDisplayDpi);
3865            callbacks = collectComponentCallbacksLocked(false, config);
3866        }
3867
3868        // Cleanup hardware accelerated stuff
3869        WindowManagerGlobal.getInstance().trimLocalMemory();
3870
3871        freeTextLayoutCachesIfNeeded(configDiff);
3872
3873        if (callbacks != null) {
3874            final int N = callbacks.size();
3875            for (int i=0; i<N; i++) {
3876                performConfigurationChanged(callbacks.get(i), config);
3877            }
3878        }
3879    }
3880
3881    final void freeTextLayoutCachesIfNeeded(int configDiff) {
3882        if (configDiff != 0) {
3883            // Ask text layout engine to free its caches if there is a locale change
3884            boolean hasLocaleConfigChange = ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0);
3885            if (hasLocaleConfigChange) {
3886                Canvas.freeTextLayoutCaches();
3887                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Cleared TextLayout Caches");
3888            }
3889        }
3890    }
3891
3892    final void handleActivityConfigurationChanged(IBinder token) {
3893        ActivityClientRecord r = mActivities.get(token);
3894        if (r == null || r.activity == null) {
3895            return;
3896        }
3897
3898        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
3899                + r.activityInfo.name);
3900
3901        performConfigurationChanged(r.activity, mCompatConfiguration);
3902
3903        freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(mCompatConfiguration));
3904    }
3905
3906    final void handleProfilerControl(boolean start, ProfilerControlData pcd, int profileType) {
3907        if (start) {
3908            try {
3909                switch (profileType) {
3910                    default:
3911                        mProfiler.setProfiler(pcd.path, pcd.fd);
3912                        mProfiler.autoStopProfiler = false;
3913                        mProfiler.startProfiling();
3914                        break;
3915                }
3916            } catch (RuntimeException e) {
3917                Slog.w(TAG, "Profiling failed on path " + pcd.path
3918                        + " -- can the process access this path?");
3919            } finally {
3920                try {
3921                    pcd.fd.close();
3922                } catch (IOException e) {
3923                    Slog.w(TAG, "Failure closing profile fd", e);
3924                }
3925            }
3926        } else {
3927            switch (profileType) {
3928                default:
3929                    mProfiler.stopProfiling();
3930                    break;
3931            }
3932        }
3933    }
3934
3935    static final void handleDumpHeap(boolean managed, DumpHeapData dhd) {
3936        if (managed) {
3937            try {
3938                Debug.dumpHprofData(dhd.path, dhd.fd.getFileDescriptor());
3939            } catch (IOException e) {
3940                Slog.w(TAG, "Managed heap dump failed on path " + dhd.path
3941                        + " -- can the process access this path?");
3942            } finally {
3943                try {
3944                    dhd.fd.close();
3945                } catch (IOException e) {
3946                    Slog.w(TAG, "Failure closing profile fd", e);
3947                }
3948            }
3949        } else {
3950            Debug.dumpNativeHeap(dhd.fd.getFileDescriptor());
3951        }
3952    }
3953
3954    final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
3955        boolean hasPkgInfo = false;
3956        if (packages != null) {
3957            for (int i=packages.length-1; i>=0; i--) {
3958                //Slog.i(TAG, "Cleaning old package: " + packages[i]);
3959                if (!hasPkgInfo) {
3960                    WeakReference<LoadedApk> ref;
3961                    ref = mPackages.get(packages[i]);
3962                    if (ref != null && ref.get() != null) {
3963                        hasPkgInfo = true;
3964                    } else {
3965                        ref = mResourcePackages.get(packages[i]);
3966                        if (ref != null && ref.get() != null) {
3967                            hasPkgInfo = true;
3968                        }
3969                    }
3970                }
3971                mPackages.remove(packages[i]);
3972                mResourcePackages.remove(packages[i]);
3973            }
3974        }
3975        ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
3976                hasPkgInfo);
3977    }
3978
3979    final void handleLowMemory() {
3980        ArrayList<ComponentCallbacks2> callbacks;
3981
3982        synchronized (mPackages) {
3983            callbacks = collectComponentCallbacksLocked(true, null);
3984        }
3985
3986        final int N = callbacks.size();
3987        for (int i=0; i<N; i++) {
3988            callbacks.get(i).onLowMemory();
3989        }
3990
3991        // Ask SQLite to free up as much memory as it can, mostly from its page caches.
3992        if (Process.myUid() != Process.SYSTEM_UID) {
3993            int sqliteReleased = SQLiteDatabase.releaseMemory();
3994            EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
3995        }
3996
3997        // Ask graphics to free up as much as possible (font/image caches)
3998        Canvas.freeCaches();
3999
4000        // Ask text layout engine to free also as much as possible
4001        Canvas.freeTextLayoutCaches();
4002
4003        BinderInternal.forceGc("mem");
4004    }
4005
4006    final void handleTrimMemory(int level) {
4007        if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level);
4008
4009        final WindowManagerGlobal windowManager = WindowManagerGlobal.getInstance();
4010        windowManager.startTrimMemory(level);
4011
4012        ArrayList<ComponentCallbacks2> callbacks;
4013        synchronized (mPackages) {
4014            callbacks = collectComponentCallbacksLocked(true, null);
4015        }
4016
4017        final int N = callbacks.size();
4018        for (int i = 0; i < N; i++) {
4019            callbacks.get(i).onTrimMemory(level);
4020        }
4021
4022        windowManager.endTrimMemory();
4023    }
4024
4025    private void setupGraphicsSupport(LoadedApk info, File cacheDir) {
4026        if (Process.isIsolated()) {
4027            // Isolated processes aren't going to do UI.
4028            return;
4029        }
4030        try {
4031            int uid = Process.myUid();
4032            String[] packages = getPackageManager().getPackagesForUid(uid);
4033
4034            // If there are several packages in this application we won't
4035            // initialize the graphics disk caches
4036            if (packages != null && packages.length == 1) {
4037                HardwareRenderer.setupDiskCache(cacheDir);
4038                RenderScript.setupDiskCache(cacheDir);
4039            }
4040        } catch (RemoteException e) {
4041            // Ignore
4042        }
4043    }
4044
4045    private void updateDefaultDensity() {
4046        if (mCurDefaultDisplayDpi != Configuration.DENSITY_DPI_UNDEFINED
4047                && mCurDefaultDisplayDpi != DisplayMetrics.DENSITY_DEVICE
4048                && !mDensityCompatMode) {
4049            Slog.i(TAG, "Switching default density from "
4050                    + DisplayMetrics.DENSITY_DEVICE + " to "
4051                    + mCurDefaultDisplayDpi);
4052            DisplayMetrics.DENSITY_DEVICE = mCurDefaultDisplayDpi;
4053            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
4054        }
4055    }
4056
4057    private void handleBindApplication(AppBindData data) {
4058        mBoundApplication = data;
4059        mConfiguration = new Configuration(data.config);
4060        mCompatConfiguration = new Configuration(data.config);
4061
4062        mProfiler = new Profiler();
4063        mProfiler.profileFile = data.initProfileFile;
4064        mProfiler.profileFd = data.initProfileFd;
4065        mProfiler.autoStopProfiler = data.initAutoStopProfiler;
4066
4067        // send up app name; do this *before* waiting for debugger
4068        Process.setArgV0(data.processName);
4069        android.ddm.DdmHandleAppName.setAppName(data.processName,
4070                                                UserHandle.myUserId());
4071
4072        if (data.persistent) {
4073            // Persistent processes on low-memory devices do not get to
4074            // use hardware accelerated drawing, since this can add too much
4075            // overhead to the process.
4076            if (!ActivityManager.isHighEndGfx()) {
4077                HardwareRenderer.disable(false);
4078            }
4079        }
4080
4081        if (mProfiler.profileFd != null) {
4082            mProfiler.startProfiling();
4083        }
4084
4085        // If the app is Honeycomb MR1 or earlier, switch its AsyncTask
4086        // implementation to use the pool executor.  Normally, we use the
4087        // serialized executor as the default. This has to happen in the
4088        // main thread so the main looper is set right.
4089        if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
4090            AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
4091        }
4092
4093        /*
4094         * Before spawning a new process, reset the time zone to be the system time zone.
4095         * This needs to be done because the system time zone could have changed after the
4096         * the spawning of this process. Without doing this this process would have the incorrect
4097         * system time zone.
4098         */
4099        TimeZone.setDefault(null);
4100
4101        /*
4102         * Initialize the default locale in this process for the reasons we set the time zone.
4103         */
4104        Locale.setDefault(data.config.locale);
4105
4106        /*
4107         * Update the system configuration since its preloaded and might not
4108         * reflect configuration changes. The configuration object passed
4109         * in AppBindData can be safely assumed to be up to date
4110         */
4111        applyConfigurationToResourcesLocked(data.config, data.compatInfo);
4112        mCurDefaultDisplayDpi = data.config.densityDpi;
4113        applyCompatConfiguration(mCurDefaultDisplayDpi);
4114
4115        data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
4116
4117        /**
4118         * Switch this process to density compatibility mode if needed.
4119         */
4120        if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
4121                == 0) {
4122            mDensityCompatMode = true;
4123            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
4124        }
4125        updateDefaultDensity();
4126
4127        final ContextImpl appContext = new ContextImpl();
4128        appContext.init(data.info, null, this);
4129        if (!Process.isIsolated()) {
4130            final File cacheDir = appContext.getCacheDir();
4131
4132            if (cacheDir != null) {
4133                // Provide a usable directory for temporary files
4134                System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
4135
4136                setupGraphicsSupport(data.info, cacheDir);
4137            } else {
4138                Log.e(TAG, "Unable to setupGraphicsSupport due to missing cache directory");
4139            }
4140        }
4141        /**
4142         * For system applications on userdebug/eng builds, log stack
4143         * traces of disk and network access to dropbox for analysis.
4144         */
4145        if ((data.appInfo.flags &
4146             (ApplicationInfo.FLAG_SYSTEM |
4147              ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) {
4148            StrictMode.conditionallyEnableDebugLogging();
4149        }
4150
4151        /**
4152         * For apps targetting SDK Honeycomb or later, we don't allow
4153         * network usage on the main event loop / UI thread.
4154         *
4155         * Note to those grepping:  this is what ultimately throws
4156         * NetworkOnMainThreadException ...
4157         */
4158        if (data.appInfo.targetSdkVersion > 9) {
4159            StrictMode.enableDeathOnNetwork();
4160        }
4161
4162        if (data.debugMode != IApplicationThread.DEBUG_OFF) {
4163            // XXX should have option to change the port.
4164            Debug.changeDebugPort(8100);
4165            if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
4166                Slog.w(TAG, "Application " + data.info.getPackageName()
4167                      + " is waiting for the debugger on port 8100...");
4168
4169                IActivityManager mgr = ActivityManagerNative.getDefault();
4170                try {
4171                    mgr.showWaitingForDebugger(mAppThread, true);
4172                } catch (RemoteException ex) {
4173                }
4174
4175                Debug.waitForDebugger();
4176
4177                try {
4178                    mgr.showWaitingForDebugger(mAppThread, false);
4179                } catch (RemoteException ex) {
4180                }
4181
4182            } else {
4183                Slog.w(TAG, "Application " + data.info.getPackageName()
4184                      + " can be debugged on port 8100...");
4185            }
4186        }
4187
4188        // Enable OpenGL tracing if required
4189        if (data.enableOpenGlTrace) {
4190            GLUtils.enableTracing();
4191        }
4192
4193        /**
4194         * Initialize the default http proxy in this process for the reasons we set the time zone.
4195         */
4196        IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
4197        if (b != null) {
4198            // In pre-boot mode (doing initial launch to collect password), not
4199            // all system is up.  This includes the connectivity service, so don't
4200            // crash if we can't get it.
4201            IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
4202            try {
4203                ProxyProperties proxyProperties = service.getProxy();
4204                Proxy.setHttpProxySystemProperty(proxyProperties);
4205            } catch (RemoteException e) {}
4206        }
4207
4208        if (data.instrumentationName != null) {
4209            InstrumentationInfo ii = null;
4210            try {
4211                ii = appContext.getPackageManager().
4212                    getInstrumentationInfo(data.instrumentationName, 0);
4213            } catch (PackageManager.NameNotFoundException e) {
4214            }
4215            if (ii == null) {
4216                throw new RuntimeException(
4217                    "Unable to find instrumentation info for: "
4218                    + data.instrumentationName);
4219            }
4220
4221            mInstrumentationAppDir = ii.sourceDir;
4222            mInstrumentationAppLibraryDir = ii.nativeLibraryDir;
4223            mInstrumentationAppPackage = ii.packageName;
4224            mInstrumentedAppDir = data.info.getAppDir();
4225            mInstrumentedAppLibraryDir = data.info.getLibDir();
4226
4227            ApplicationInfo instrApp = new ApplicationInfo();
4228            instrApp.packageName = ii.packageName;
4229            instrApp.sourceDir = ii.sourceDir;
4230            instrApp.publicSourceDir = ii.publicSourceDir;
4231            instrApp.dataDir = ii.dataDir;
4232            instrApp.nativeLibraryDir = ii.nativeLibraryDir;
4233            LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
4234                    appContext.getClassLoader(), false, true);
4235            ContextImpl instrContext = new ContextImpl();
4236            instrContext.init(pi, null, this);
4237
4238            try {
4239                java.lang.ClassLoader cl = instrContext.getClassLoader();
4240                mInstrumentation = (Instrumentation)
4241                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
4242            } catch (Exception e) {
4243                throw new RuntimeException(
4244                    "Unable to instantiate instrumentation "
4245                    + data.instrumentationName + ": " + e.toString(), e);
4246            }
4247
4248            mInstrumentation.init(this, instrContext, appContext,
4249                    new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);
4250
4251            if (mProfiler.profileFile != null && !ii.handleProfiling
4252                    && mProfiler.profileFd == null) {
4253                mProfiler.handlingProfiling = true;
4254                File file = new File(mProfiler.profileFile);
4255                file.getParentFile().mkdirs();
4256                Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
4257            }
4258
4259        } else {
4260            mInstrumentation = new Instrumentation();
4261        }
4262
4263        if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
4264            dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
4265        }
4266
4267        // Allow disk access during application and provider setup. This could
4268        // block processing ordered broadcasts, but later processing would
4269        // probably end up doing the same disk access.
4270        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
4271        try {
4272            // If the app is being launched for full backup or restore, bring it up in
4273            // a restricted environment with the base application class.
4274            Application app = data.info.makeApplication(data.restrictedBackupMode, null);
4275            mInitialApplication = app;
4276
4277            // don't bring up providers in restricted mode; they may depend on the
4278            // app's custom Application class
4279            if (!data.restrictedBackupMode) {
4280                List<ProviderInfo> providers = data.providers;
4281                if (providers != null) {
4282                    installContentProviders(app, providers);
4283                    // For process that contains content providers, we want to
4284                    // ensure that the JIT is enabled "at some point".
4285                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
4286                }
4287            }
4288
4289            // Do this after providers, since instrumentation tests generally start their
4290            // test thread at this point, and we don't want that racing.
4291            try {
4292                mInstrumentation.onCreate(data.instrumentationArgs);
4293            }
4294            catch (Exception e) {
4295                throw new RuntimeException(
4296                    "Exception thrown in onCreate() of "
4297                    + data.instrumentationName + ": " + e.toString(), e);
4298            }
4299
4300            try {
4301                mInstrumentation.callApplicationOnCreate(app);
4302            } catch (Exception e) {
4303                if (!mInstrumentation.onException(app, e)) {
4304                    throw new RuntimeException(
4305                        "Unable to create application " + app.getClass().getName()
4306                        + ": " + e.toString(), e);
4307                }
4308            }
4309        } finally {
4310            StrictMode.setThreadPolicy(savedPolicy);
4311        }
4312    }
4313
4314    /*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
4315        IActivityManager am = ActivityManagerNative.getDefault();
4316        if (mProfiler.profileFile != null && mProfiler.handlingProfiling
4317                && mProfiler.profileFd == null) {
4318            Debug.stopMethodTracing();
4319        }
4320        //Slog.i(TAG, "am: " + ActivityManagerNative.getDefault()
4321        //      + ", app thr: " + mAppThread);
4322        try {
4323            am.finishInstrumentation(mAppThread, resultCode, results);
4324        } catch (RemoteException ex) {
4325        }
4326    }
4327
4328    private void installContentProviders(
4329            Context context, List<ProviderInfo> providers) {
4330        final ArrayList<IActivityManager.ContentProviderHolder> results =
4331            new ArrayList<IActivityManager.ContentProviderHolder>();
4332
4333        for (ProviderInfo cpi : providers) {
4334            StringBuilder buf = new StringBuilder(128);
4335            buf.append("Pub ");
4336            buf.append(cpi.authority);
4337            buf.append(": ");
4338            buf.append(cpi.name);
4339            Log.i(TAG, buf.toString());
4340            IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
4341                    false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
4342            if (cph != null) {
4343                cph.noReleaseNeeded = true;
4344                results.add(cph);
4345            }
4346        }
4347
4348        try {
4349            ActivityManagerNative.getDefault().publishContentProviders(
4350                getApplicationThread(), results);
4351        } catch (RemoteException ex) {
4352        }
4353    }
4354
4355    public final IContentProvider acquireProvider(Context c, String name, boolean stable) {
4356        IContentProvider provider = acquireExistingProvider(c, name, stable);
4357        if (provider != null) {
4358            return provider;
4359        }
4360
4361        // There is a possible race here.  Another thread may try to acquire
4362        // the same provider at the same time.  When this happens, we want to ensure
4363        // that the first one wins.
4364        // Note that we cannot hold the lock while acquiring and installing the
4365        // provider since it might take a long time to run and it could also potentially
4366        // be re-entrant in the case where the provider is in the same process.
4367        IActivityManager.ContentProviderHolder holder = null;
4368        try {
4369            holder = ActivityManagerNative.getDefault().getContentProvider(
4370                    getApplicationThread(), name, stable);
4371        } catch (RemoteException ex) {
4372        }
4373        if (holder == null) {
4374            Slog.e(TAG, "Failed to find provider info for " + name);
4375            return null;
4376        }
4377
4378        // Install provider will increment the reference count for us, and break
4379        // any ties in the race.
4380        holder = installProvider(c, holder, holder.info,
4381                true /*noisy*/, holder.noReleaseNeeded, stable);
4382        return holder.provider;
4383    }
4384
4385    private final void incProviderRefLocked(ProviderRefCount prc, boolean stable) {
4386        if (stable) {
4387            prc.stableCount += 1;
4388            if (prc.stableCount == 1) {
4389                // We are acquiring a new stable reference on the provider.
4390                int unstableDelta;
4391                if (prc.removePending) {
4392                    // We have a pending remove operation, which is holding the
4393                    // last unstable reference.  At this point we are converting
4394                    // that unstable reference to our new stable reference.
4395                    unstableDelta = -1;
4396                    // Cancel the removal of the provider.
4397                    if (DEBUG_PROVIDER) {
4398                        Slog.v(TAG, "incProviderRef: stable "
4399                                + "snatched provider from the jaws of death");
4400                    }
4401                    prc.removePending = false;
4402                    mH.removeMessages(H.REMOVE_PROVIDER, prc);
4403                } else {
4404                    unstableDelta = 0;
4405                }
4406                try {
4407                    if (DEBUG_PROVIDER) {
4408                        Slog.v(TAG, "incProviderRef Now stable - "
4409                                + prc.holder.info.name + ": unstableDelta="
4410                                + unstableDelta);
4411                    }
4412                    ActivityManagerNative.getDefault().refContentProvider(
4413                            prc.holder.connection, 1, unstableDelta);
4414                } catch (RemoteException e) {
4415                    //do nothing content provider object is dead any way
4416                }
4417            }
4418        } else {
4419            prc.unstableCount += 1;
4420            if (prc.unstableCount == 1) {
4421                // We are acquiring a new unstable reference on the provider.
4422                if (prc.removePending) {
4423                    // Oh look, we actually have a remove pending for the
4424                    // provider, which is still holding the last unstable
4425                    // reference.  We just need to cancel that to take new
4426                    // ownership of the reference.
4427                    if (DEBUG_PROVIDER) {
4428                        Slog.v(TAG, "incProviderRef: unstable "
4429                                + "snatched provider from the jaws of death");
4430                    }
4431                    prc.removePending = false;
4432                    mH.removeMessages(H.REMOVE_PROVIDER, prc);
4433                } else {
4434                    // First unstable ref, increment our count in the
4435                    // activity manager.
4436                    try {
4437                        if (DEBUG_PROVIDER) {
4438                            Slog.v(TAG, "incProviderRef: Now unstable - "
4439                                    + prc.holder.info.name);
4440                        }
4441                        ActivityManagerNative.getDefault().refContentProvider(
4442                                prc.holder.connection, 0, 1);
4443                    } catch (RemoteException e) {
4444                        //do nothing content provider object is dead any way
4445                    }
4446                }
4447            }
4448        }
4449    }
4450
4451    public final IContentProvider acquireExistingProvider(Context c, String name,
4452            boolean stable) {
4453        synchronized (mProviderMap) {
4454            ProviderClientRecord pr = mProviderMap.get(name);
4455            if (pr == null) {
4456                return null;
4457            }
4458
4459            IContentProvider provider = pr.mProvider;
4460            IBinder jBinder = provider.asBinder();
4461
4462            // Only increment the ref count if we have one.  If we don't then the
4463            // provider is not reference counted and never needs to be released.
4464            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4465            if (prc != null) {
4466                incProviderRefLocked(prc, stable);
4467            }
4468            return provider;
4469        }
4470    }
4471
4472    public final boolean releaseProvider(IContentProvider provider, boolean stable) {
4473        if (provider == null) {
4474            return false;
4475        }
4476
4477        IBinder jBinder = provider.asBinder();
4478        synchronized (mProviderMap) {
4479            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4480            if (prc == null) {
4481                // The provider has no ref count, no release is needed.
4482                return false;
4483            }
4484
4485            boolean lastRef = false;
4486            if (stable) {
4487                if (prc.stableCount == 0) {
4488                    if (DEBUG_PROVIDER) Slog.v(TAG,
4489                            "releaseProvider: stable ref count already 0, how?");
4490                    return false;
4491                }
4492                prc.stableCount -= 1;
4493                if (prc.stableCount == 0) {
4494                    // What we do at this point depends on whether there are
4495                    // any unstable refs left: if there are, we just tell the
4496                    // activity manager to decrement its stable count; if there
4497                    // aren't, we need to enqueue this provider to be removed,
4498                    // and convert to holding a single unstable ref while
4499                    // doing so.
4500                    lastRef = prc.unstableCount == 0;
4501                    try {
4502                        if (DEBUG_PROVIDER) {
4503                            Slog.v(TAG, "releaseProvider: No longer stable w/lastRef="
4504                                    + lastRef + " - " + prc.holder.info.name);
4505                        }
4506                        ActivityManagerNative.getDefault().refContentProvider(
4507                                prc.holder.connection, -1, lastRef ? 1 : 0);
4508                    } catch (RemoteException e) {
4509                        //do nothing content provider object is dead any way
4510                    }
4511                }
4512            } else {
4513                if (prc.unstableCount == 0) {
4514                    if (DEBUG_PROVIDER) Slog.v(TAG,
4515                            "releaseProvider: unstable ref count already 0, how?");
4516                    return false;
4517                }
4518                prc.unstableCount -= 1;
4519                if (prc.unstableCount == 0) {
4520                    // If this is the last reference, we need to enqueue
4521                    // this provider to be removed instead of telling the
4522                    // activity manager to remove it at this point.
4523                    lastRef = prc.stableCount == 0;
4524                    if (!lastRef) {
4525                        try {
4526                            if (DEBUG_PROVIDER) {
4527                                Slog.v(TAG, "releaseProvider: No longer unstable - "
4528                                        + prc.holder.info.name);
4529                            }
4530                            ActivityManagerNative.getDefault().refContentProvider(
4531                                    prc.holder.connection, 0, -1);
4532                        } catch (RemoteException e) {
4533                            //do nothing content provider object is dead any way
4534                        }
4535                    }
4536                }
4537            }
4538
4539            if (lastRef) {
4540                if (!prc.removePending) {
4541                    // Schedule the actual remove asynchronously, since we don't know the context
4542                    // this will be called in.
4543                    // TODO: it would be nice to post a delayed message, so
4544                    // if we come back and need the same provider quickly
4545                    // we will still have it available.
4546                    if (DEBUG_PROVIDER) {
4547                        Slog.v(TAG, "releaseProvider: Enqueueing pending removal - "
4548                                + prc.holder.info.name);
4549                    }
4550                    prc.removePending = true;
4551                    Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, prc);
4552                    mH.sendMessage(msg);
4553                } else {
4554                    Slog.w(TAG, "Duplicate remove pending of provider " + prc.holder.info.name);
4555                }
4556            }
4557            return true;
4558        }
4559    }
4560
4561    final void completeRemoveProvider(ProviderRefCount prc) {
4562        synchronized (mProviderMap) {
4563            if (!prc.removePending) {
4564                // There was a race!  Some other client managed to acquire
4565                // the provider before the removal was completed.
4566                // Abort the removal.  We will do it later.
4567                if (DEBUG_PROVIDER) Slog.v(TAG, "completeRemoveProvider: lost the race, "
4568                        + "provider still in use");
4569                return;
4570            }
4571
4572            final IBinder jBinder = prc.holder.provider.asBinder();
4573            ProviderRefCount existingPrc = mProviderRefCountMap.get(jBinder);
4574            if (existingPrc == prc) {
4575                mProviderRefCountMap.remove(jBinder);
4576            }
4577
4578            Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator();
4579            while (iter.hasNext()) {
4580                ProviderClientRecord pr = iter.next();
4581                IBinder myBinder = pr.mProvider.asBinder();
4582                if (myBinder == jBinder) {
4583                    iter.remove();
4584                }
4585            }
4586        }
4587
4588        try {
4589            if (DEBUG_PROVIDER) {
4590                Slog.v(TAG, "removeProvider: Invoking ActivityManagerNative."
4591                        + "removeContentProvider(" + prc.holder.info.name + ")");
4592            }
4593            ActivityManagerNative.getDefault().removeContentProvider(
4594                    prc.holder.connection, false);
4595        } catch (RemoteException e) {
4596            //do nothing content provider object is dead any way
4597        }
4598    }
4599
4600    final void handleUnstableProviderDied(IBinder provider, boolean fromClient) {
4601        synchronized(mProviderMap) {
4602            ProviderRefCount prc = mProviderRefCountMap.get(provider);
4603            if (prc != null) {
4604                if (DEBUG_PROVIDER) Slog.v(TAG, "Cleaning up dead provider "
4605                        + provider + " " + prc.holder.info.name);
4606                mProviderRefCountMap.remove(provider);
4607                if (prc.client != null && prc.client.mNames != null) {
4608                    for (String name : prc.client.mNames) {
4609                        ProviderClientRecord pr = mProviderMap.get(name);
4610                        if (pr != null && pr.mProvider.asBinder() == provider) {
4611                            Slog.i(TAG, "Removing dead content provider: " + name);
4612                            mProviderMap.remove(name);
4613                        }
4614                    }
4615                }
4616                if (fromClient) {
4617                    // We found out about this due to execution in our client
4618                    // code.  Tell the activity manager about it now, to ensure
4619                    // that the next time we go to do anything with the provider
4620                    // it knows it is dead (so we don't race with its death
4621                    // notification).
4622                    try {
4623                        ActivityManagerNative.getDefault().unstableProviderDied(
4624                                prc.holder.connection);
4625                    } catch (RemoteException e) {
4626                        //do nothing content provider object is dead any way
4627                    }
4628                }
4629            }
4630        }
4631    }
4632
4633    private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,
4634            ContentProvider localProvider,IActivityManager.ContentProviderHolder holder) {
4635        String names[] = PATTERN_SEMICOLON.split(holder.info.authority);
4636        ProviderClientRecord pcr = new ProviderClientRecord(names, provider,
4637                localProvider, holder);
4638        for (int i = 0; i < names.length; i++) {
4639            ProviderClientRecord existing = mProviderMap.get(names[i]);
4640            if (existing != null) {
4641                Slog.w(TAG, "Content provider " + pcr.mHolder.info.name
4642                        + " already published as " + names[i]);
4643            } else {
4644                mProviderMap.put(names[i], pcr);
4645            }
4646        }
4647        return pcr;
4648    }
4649
4650    /**
4651     * Installs the provider.
4652     *
4653     * Providers that are local to the process or that come from the system server
4654     * may be installed permanently which is indicated by setting noReleaseNeeded to true.
4655     * Other remote providers are reference counted.  The initial reference count
4656     * for all reference counted providers is one.  Providers that are not reference
4657     * counted do not have a reference count (at all).
4658     *
4659     * This method detects when a provider has already been installed.  When this happens,
4660     * it increments the reference count of the existing provider (if appropriate)
4661     * and returns the existing provider.  This can happen due to concurrent
4662     * attempts to acquire the same provider.
4663     */
4664    private IActivityManager.ContentProviderHolder installProvider(Context context,
4665            IActivityManager.ContentProviderHolder holder, ProviderInfo info,
4666            boolean noisy, boolean noReleaseNeeded, boolean stable) {
4667        ContentProvider localProvider = null;
4668        IContentProvider provider;
4669        if (holder == null || holder.provider == null) {
4670            if (DEBUG_PROVIDER || noisy) {
4671                Slog.d(TAG, "Loading provider " + info.authority + ": "
4672                        + info.name);
4673            }
4674            Context c = null;
4675            ApplicationInfo ai = info.applicationInfo;
4676            if (context.getPackageName().equals(ai.packageName)) {
4677                c = context;
4678            } else if (mInitialApplication != null &&
4679                    mInitialApplication.getPackageName().equals(ai.packageName)) {
4680                c = mInitialApplication;
4681            } else {
4682                try {
4683                    c = context.createPackageContext(ai.packageName,
4684                            Context.CONTEXT_INCLUDE_CODE);
4685                } catch (PackageManager.NameNotFoundException e) {
4686                    // Ignore
4687                }
4688            }
4689            if (c == null) {
4690                Slog.w(TAG, "Unable to get context for package " +
4691                      ai.packageName +
4692                      " while loading content provider " +
4693                      info.name);
4694                return null;
4695            }
4696            try {
4697                final java.lang.ClassLoader cl = c.getClassLoader();
4698                localProvider = (ContentProvider)cl.
4699                    loadClass(info.name).newInstance();
4700                provider = localProvider.getIContentProvider();
4701                if (provider == null) {
4702                    Slog.e(TAG, "Failed to instantiate class " +
4703                          info.name + " from sourceDir " +
4704                          info.applicationInfo.sourceDir);
4705                    return null;
4706                }
4707                if (DEBUG_PROVIDER) Slog.v(
4708                    TAG, "Instantiating local provider " + info.name);
4709                // XXX Need to create the correct context for this provider.
4710                localProvider.attachInfo(c, info);
4711            } catch (java.lang.Exception e) {
4712                if (!mInstrumentation.onException(null, e)) {
4713                    throw new RuntimeException(
4714                            "Unable to get provider " + info.name
4715                            + ": " + e.toString(), e);
4716                }
4717                return null;
4718            }
4719        } else {
4720            provider = holder.provider;
4721            if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": "
4722                    + info.name);
4723        }
4724
4725        IActivityManager.ContentProviderHolder retHolder;
4726
4727        synchronized (mProviderMap) {
4728            if (DEBUG_PROVIDER) Slog.v(TAG, "Checking to add " + provider
4729                    + " / " + info.name);
4730            IBinder jBinder = provider.asBinder();
4731            if (localProvider != null) {
4732                ComponentName cname = new ComponentName(info.packageName, info.name);
4733                ProviderClientRecord pr = mLocalProvidersByName.get(cname);
4734                if (pr != null) {
4735                    if (DEBUG_PROVIDER) {
4736                        Slog.v(TAG, "installProvider: lost the race, "
4737                                + "using existing local provider");
4738                    }
4739                    provider = pr.mProvider;
4740                } else {
4741                    holder = new IActivityManager.ContentProviderHolder(info);
4742                    holder.provider = provider;
4743                    holder.noReleaseNeeded = true;
4744                    pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
4745                    mLocalProviders.put(jBinder, pr);
4746                    mLocalProvidersByName.put(cname, pr);
4747                }
4748                retHolder = pr.mHolder;
4749            } else {
4750                ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4751                if (prc != null) {
4752                    if (DEBUG_PROVIDER) {
4753                        Slog.v(TAG, "installProvider: lost the race, updating ref count");
4754                    }
4755                    // We need to transfer our new reference to the existing
4756                    // ref count, releasing the old one...  but only if
4757                    // release is needed (that is, it is not running in the
4758                    // system process).
4759                    if (!noReleaseNeeded) {
4760                        incProviderRefLocked(prc, stable);
4761                        try {
4762                            ActivityManagerNative.getDefault().removeContentProvider(
4763                                    holder.connection, stable);
4764                        } catch (RemoteException e) {
4765                            //do nothing content provider object is dead any way
4766                        }
4767                    }
4768                } else {
4769                    ProviderClientRecord client = installProviderAuthoritiesLocked(
4770                            provider, localProvider, holder);
4771                    if (noReleaseNeeded) {
4772                        prc = new ProviderRefCount(holder, client, 1000, 1000);
4773                    } else {
4774                        prc = stable
4775                                ? new ProviderRefCount(holder, client, 1, 0)
4776                                : new ProviderRefCount(holder, client, 0, 1);
4777                    }
4778                    mProviderRefCountMap.put(jBinder, prc);
4779                }
4780                retHolder = prc.holder;
4781            }
4782        }
4783
4784        return retHolder;
4785    }
4786
4787    private void attach(boolean system) {
4788        sThreadLocal.set(this);
4789        mSystemThread = system;
4790        if (!system) {
4791            ViewRootImpl.addFirstDrawHandler(new Runnable() {
4792                public void run() {
4793                    ensureJitEnabled();
4794                }
4795            });
4796            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
4797                                                    UserHandle.myUserId());
4798            RuntimeInit.setApplicationObject(mAppThread.asBinder());
4799            IActivityManager mgr = ActivityManagerNative.getDefault();
4800            try {
4801                mgr.attachApplication(mAppThread);
4802            } catch (RemoteException ex) {
4803                // Ignore
4804            }
4805        } else {
4806            // Don't set application object here -- if the system crashes,
4807            // we can't display an alert, we just want to die die die.
4808            android.ddm.DdmHandleAppName.setAppName("system_process",
4809                                                    UserHandle.myUserId());
4810            try {
4811                mInstrumentation = new Instrumentation();
4812                ContextImpl context = new ContextImpl();
4813                context.init(getSystemContext().mPackageInfo, null, this);
4814                Application app = Instrumentation.newApplication(Application.class, context);
4815                mAllApplications.add(app);
4816                mInitialApplication = app;
4817                app.onCreate();
4818            } catch (Exception e) {
4819                throw new RuntimeException(
4820                        "Unable to instantiate Application():" + e.toString(), e);
4821            }
4822        }
4823
4824        ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
4825            public void onConfigurationChanged(Configuration newConfig) {
4826                synchronized (mPackages) {
4827                    // We need to apply this change to the resources
4828                    // immediately, because upon returning the view
4829                    // hierarchy will be informed about it.
4830                    if (applyConfigurationToResourcesLocked(newConfig, null)) {
4831                        // This actually changed the resources!  Tell
4832                        // everyone about it.
4833                        if (mPendingConfiguration == null ||
4834                                mPendingConfiguration.isOtherSeqNewer(newConfig)) {
4835                            mPendingConfiguration = newConfig;
4836
4837                            queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
4838                        }
4839                    }
4840                }
4841            }
4842            public void onLowMemory() {
4843            }
4844            public void onTrimMemory(int level) {
4845            }
4846        });
4847    }
4848
4849    public static ActivityThread systemMain() {
4850        HardwareRenderer.disable(true);
4851        ActivityThread thread = new ActivityThread();
4852        thread.attach(true);
4853        return thread;
4854    }
4855
4856    public final void installSystemProviders(List<ProviderInfo> providers) {
4857        if (providers != null) {
4858            installContentProviders(mInitialApplication, providers);
4859        }
4860    }
4861
4862    public int getIntCoreSetting(String key, int defaultValue) {
4863        synchronized (mPackages) {
4864            if (mCoreSettings != null) {
4865                return mCoreSettings.getInt(key, defaultValue);
4866            } else {
4867                return defaultValue;
4868            }
4869        }
4870    }
4871
4872    public static void main(String[] args) {
4873        SamplingProfilerIntegration.start();
4874
4875        // CloseGuard defaults to true and can be quite spammy.  We
4876        // disable it here, but selectively enable it later (via
4877        // StrictMode) on debug builds, but using DropBox, not logs.
4878        CloseGuard.setEnabled(false);
4879
4880        Environment.initForCurrentUser();
4881
4882        Process.setArgV0("<pre-initialized>");
4883
4884        Looper.prepareMainLooper();
4885
4886        ActivityThread thread = new ActivityThread();
4887        thread.attach(false);
4888
4889        if (sMainThreadHandler == null) {
4890            sMainThreadHandler = thread.getHandler();
4891        }
4892
4893        AsyncTask.init();
4894
4895        if (false) {
4896            Looper.myLooper().setMessageLogging(new
4897                    LogPrinter(Log.DEBUG, "ActivityThread"));
4898        }
4899
4900        Looper.loop();
4901
4902        throw new RuntimeException("Main thread loop unexpectedly exited");
4903    }
4904}
4905