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