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