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