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