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