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