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