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