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