ActivityThread.java revision 26698514fbac587675221149aca98f3ea6414d55
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 =
2442                            dm.getCompatibleDisplay(id, appContext.getDisplayAdjustments(id));
2443                    baseContext = appContext.createDisplayContext(display);
2444                    break;
2445                }
2446            }
2447        }
2448        return baseContext;
2449    }
2450
2451    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
2452        // If we are getting ready to gc after going to the background, well
2453        // we are back active so skip it.
2454        unscheduleGcIdler();
2455        mSomeActivitiesChanged = true;
2456
2457        if (r.profilerInfo != null) {
2458            mProfiler.setProfiler(r.profilerInfo);
2459            mProfiler.startProfiling();
2460        }
2461
2462        // Make sure we are running with the most recent config.
2463        handleConfigurationChanged(null, null);
2464
2465        if (localLOGV) Slog.v(
2466            TAG, "Handling launch of " + r);
2467
2468        // Initialize before creating the activity
2469        WindowManagerGlobal.initialize();
2470
2471        Activity a = performLaunchActivity(r, customIntent);
2472
2473        if (a != null) {
2474            r.createdConfig = new Configuration(mConfiguration);
2475            Bundle oldState = r.state;
2476            handleResumeActivity(r.token, false, r.isForward,
2477                    !r.activity.mFinished && !r.startsNotResumed);
2478
2479            if (!r.activity.mFinished && r.startsNotResumed) {
2480                // The activity manager actually wants this one to start out
2481                // paused, because it needs to be visible but isn't in the
2482                // foreground.  We accomplish this by going through the
2483                // normal startup (because activities expect to go through
2484                // onResume() the first time they run, before their window
2485                // is displayed), and then pausing it.  However, in this case
2486                // we do -not- need to do the full pause cycle (of freezing
2487                // and such) because the activity manager assumes it can just
2488                // retain the current state it has.
2489                try {
2490                    r.activity.mCalled = false;
2491                    mInstrumentation.callActivityOnPause(r.activity);
2492                    // We need to keep around the original state, in case
2493                    // we need to be created again.  But we only do this
2494                    // for pre-Honeycomb apps, which always save their state
2495                    // when pausing, so we can not have them save their state
2496                    // when restarting from a paused state.  For HC and later,
2497                    // we want to (and can) let the state be saved as the normal
2498                    // part of stopping the activity.
2499                    if (r.isPreHoneycomb()) {
2500                        r.state = oldState;
2501                    }
2502                    if (!r.activity.mCalled) {
2503                        throw new SuperNotCalledException(
2504                            "Activity " + r.intent.getComponent().toShortString() +
2505                            " did not call through to super.onPause()");
2506                    }
2507
2508                } catch (SuperNotCalledException e) {
2509                    throw e;
2510
2511                } catch (Exception e) {
2512                    if (!mInstrumentation.onException(r.activity, e)) {
2513                        throw new RuntimeException(
2514                                "Unable to pause activity "
2515                                + r.intent.getComponent().toShortString()
2516                                + ": " + e.toString(), e);
2517                    }
2518                }
2519                r.paused = true;
2520            }
2521        } else {
2522            // If there was an error, for any reason, tell the activity
2523            // manager to stop us.
2524            try {
2525                ActivityManagerNative.getDefault()
2526                    .finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
2527            } catch (RemoteException ex) {
2528                // Ignore
2529            }
2530        }
2531    }
2532
2533    private void deliverNewIntents(ActivityClientRecord r, List<ReferrerIntent> intents) {
2534        final int N = intents.size();
2535        for (int i=0; i<N; i++) {
2536            ReferrerIntent intent = intents.get(i);
2537            intent.setExtrasClassLoader(r.activity.getClassLoader());
2538            intent.prepareToEnterProcess();
2539            r.activity.mFragments.noteStateNotSaved();
2540            mInstrumentation.callActivityOnNewIntent(r.activity, intent);
2541        }
2542    }
2543
2544    public final void performNewIntents(IBinder token, List<ReferrerIntent> intents) {
2545        ActivityClientRecord r = mActivities.get(token);
2546        if (r != null) {
2547            final boolean resumed = !r.paused;
2548            if (resumed) {
2549                r.activity.mTemporaryPause = true;
2550                mInstrumentation.callActivityOnPause(r.activity);
2551            }
2552            deliverNewIntents(r, intents);
2553            if (resumed) {
2554                r.activity.performResume();
2555                r.activity.mTemporaryPause = false;
2556            }
2557        }
2558    }
2559
2560    private void handleNewIntent(NewIntentData data) {
2561        performNewIntents(data.token, data.intents);
2562    }
2563
2564    public void handleRequestAssistContextExtras(RequestAssistContextExtras cmd) {
2565        Bundle data = new Bundle();
2566        AssistStructure structure = null;
2567        AssistContent content = new AssistContent();
2568        ActivityClientRecord r = mActivities.get(cmd.activityToken);
2569        if (r != null) {
2570            r.activity.getApplication().dispatchOnProvideAssistData(r.activity, data);
2571            r.activity.onProvideAssistData(data);
2572            if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL) {
2573                structure = new AssistStructure(r.activity);
2574                Intent activityIntent = r.activity.getIntent();
2575                if (activityIntent != null && (r.window == null ||
2576                        (r.window.getAttributes().flags
2577                                & WindowManager.LayoutParams.FLAG_SECURE) == 0)) {
2578                    Intent intent = new Intent(activityIntent);
2579                    intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
2580                            | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION));
2581                    intent.removeUnsafeExtras();
2582                    content.setIntent(intent);
2583                } else {
2584                    content.setIntent(new Intent());
2585                }
2586                r.activity.onProvideAssistContent(content);
2587            }
2588        }
2589        if (structure == null) {
2590            structure = new AssistStructure();
2591        }
2592        IActivityManager mgr = ActivityManagerNative.getDefault();
2593        try {
2594            mgr.reportAssistContextExtras(cmd.requestToken, data, structure, content);
2595        } catch (RemoteException e) {
2596        }
2597    }
2598
2599    public void handleTranslucentConversionComplete(IBinder token, boolean drawComplete) {
2600        ActivityClientRecord r = mActivities.get(token);
2601        if (r != null) {
2602            r.activity.onTranslucentConversionComplete(drawComplete);
2603        }
2604    }
2605
2606    public void onNewActivityOptions(IBinder token, ActivityOptions options) {
2607        ActivityClientRecord r = mActivities.get(token);
2608        if (r != null) {
2609            r.activity.onNewActivityOptions(options);
2610        }
2611    }
2612
2613    public void handleCancelVisibleBehind(IBinder token) {
2614        ActivityClientRecord r = mActivities.get(token);
2615        if (r != null) {
2616            mSomeActivitiesChanged = true;
2617            final Activity activity = r.activity;
2618            if (activity.mVisibleBehind) {
2619                activity.mCalled = false;
2620                activity.onVisibleBehindCanceled();
2621                // Tick, tick, tick. The activity has 500 msec to return or it will be destroyed.
2622                if (!activity.mCalled) {
2623                    throw new SuperNotCalledException("Activity " + activity.getLocalClassName() +
2624                            " did not call through to super.onVisibleBehindCanceled()");
2625                }
2626                activity.mVisibleBehind = false;
2627            }
2628        }
2629        try {
2630            ActivityManagerNative.getDefault().backgroundResourcesReleased(token);
2631        } catch (RemoteException e) {
2632        }
2633    }
2634
2635    public void handleOnBackgroundVisibleBehindChanged(IBinder token, boolean visible) {
2636        ActivityClientRecord r = mActivities.get(token);
2637        if (r != null) {
2638            r.activity.onBackgroundVisibleBehindChanged(visible);
2639        }
2640    }
2641
2642    public void handleInstallProvider(ProviderInfo info) {
2643        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
2644        try {
2645            installContentProviders(mInitialApplication, Lists.newArrayList(info));
2646        } finally {
2647            StrictMode.setThreadPolicy(oldPolicy);
2648        }
2649    }
2650
2651    private void handleEnterAnimationComplete(IBinder token) {
2652        ActivityClientRecord r = mActivities.get(token);
2653        if (r != null) {
2654            r.activity.dispatchEnterAnimationComplete();
2655        }
2656    }
2657
2658    private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>();
2659
2660    /**
2661     * Return the Intent that's currently being handled by a
2662     * BroadcastReceiver on this thread, or null if none.
2663     * @hide
2664     */
2665    public static Intent getIntentBeingBroadcast() {
2666        return sCurrentBroadcastIntent.get();
2667    }
2668
2669    private void handleReceiver(ReceiverData data) {
2670        // If we are getting ready to gc after going to the background, well
2671        // we are back active so skip it.
2672        unscheduleGcIdler();
2673
2674        String component = data.intent.getComponent().getClassName();
2675
2676        LoadedApk packageInfo = getPackageInfoNoCheck(
2677                data.info.applicationInfo, data.compatInfo);
2678
2679        IActivityManager mgr = ActivityManagerNative.getDefault();
2680
2681        BroadcastReceiver receiver;
2682        try {
2683            java.lang.ClassLoader cl = packageInfo.getClassLoader();
2684            data.intent.setExtrasClassLoader(cl);
2685            data.intent.prepareToEnterProcess();
2686            data.setExtrasClassLoader(cl);
2687            receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
2688        } catch (Exception e) {
2689            if (DEBUG_BROADCAST) Slog.i(TAG,
2690                    "Finishing failed broadcast to " + data.intent.getComponent());
2691            data.sendFinished(mgr);
2692            throw new RuntimeException(
2693                "Unable to instantiate receiver " + component
2694                + ": " + e.toString(), e);
2695        }
2696
2697        try {
2698            Application app = packageInfo.makeApplication(false, mInstrumentation);
2699
2700            if (localLOGV) Slog.v(
2701                TAG, "Performing receive of " + data.intent
2702                + ": app=" + app
2703                + ", appName=" + app.getPackageName()
2704                + ", pkg=" + packageInfo.getPackageName()
2705                + ", comp=" + data.intent.getComponent().toShortString()
2706                + ", dir=" + packageInfo.getAppDir());
2707
2708            ContextImpl context = (ContextImpl)app.getBaseContext();
2709            sCurrentBroadcastIntent.set(data.intent);
2710            receiver.setPendingResult(data);
2711            receiver.onReceive(context.getReceiverRestrictedContext(),
2712                    data.intent);
2713        } catch (Exception e) {
2714            if (DEBUG_BROADCAST) Slog.i(TAG,
2715                    "Finishing failed broadcast to " + data.intent.getComponent());
2716            data.sendFinished(mgr);
2717            if (!mInstrumentation.onException(receiver, e)) {
2718                throw new RuntimeException(
2719                    "Unable to start receiver " + component
2720                    + ": " + e.toString(), e);
2721            }
2722        } finally {
2723            sCurrentBroadcastIntent.set(null);
2724        }
2725
2726        if (receiver.getPendingResult() != null) {
2727            data.finish();
2728        }
2729    }
2730
2731    // Instantiate a BackupAgent and tell it that it's alive
2732    private void handleCreateBackupAgent(CreateBackupAgentData data) {
2733        if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data);
2734
2735        // Sanity check the requested target package's uid against ours
2736        try {
2737            PackageInfo requestedPackage = getPackageManager().getPackageInfo(
2738                    data.appInfo.packageName, 0, UserHandle.myUserId());
2739            if (requestedPackage.applicationInfo.uid != Process.myUid()) {
2740                Slog.w(TAG, "Asked to instantiate non-matching package "
2741                        + data.appInfo.packageName);
2742                return;
2743            }
2744        } catch (RemoteException e) {
2745            Slog.e(TAG, "Can't reach package manager", e);
2746            return;
2747        }
2748
2749        // no longer idle; we have backup work to do
2750        unscheduleGcIdler();
2751
2752        // instantiate the BackupAgent class named in the manifest
2753        LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
2754        String packageName = packageInfo.mPackageName;
2755        if (packageName == null) {
2756            Slog.d(TAG, "Asked to create backup agent for nonexistent package");
2757            return;
2758        }
2759
2760        String classname = data.appInfo.backupAgentName;
2761        // full backup operation but no app-supplied agent?  use the default implementation
2762        if (classname == null && (data.backupMode == IApplicationThread.BACKUP_MODE_FULL
2763                || data.backupMode == IApplicationThread.BACKUP_MODE_RESTORE_FULL)) {
2764            classname = "android.app.backup.FullBackupAgent";
2765        }
2766
2767        try {
2768            IBinder binder = null;
2769            BackupAgent agent = mBackupAgents.get(packageName);
2770            if (agent != null) {
2771                // reusing the existing instance
2772                if (DEBUG_BACKUP) {
2773                    Slog.v(TAG, "Reusing existing agent instance");
2774                }
2775                binder = agent.onBind();
2776            } else {
2777                try {
2778                    if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname);
2779
2780                    java.lang.ClassLoader cl = packageInfo.getClassLoader();
2781                    agent = (BackupAgent) cl.loadClass(classname).newInstance();
2782
2783                    // set up the agent's context
2784                    ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
2785                    context.setOuterContext(agent);
2786                    agent.attach(context);
2787
2788                    agent.onCreate();
2789                    binder = agent.onBind();
2790                    mBackupAgents.put(packageName, agent);
2791                } catch (Exception e) {
2792                    // If this is during restore, fail silently; otherwise go
2793                    // ahead and let the user see the crash.
2794                    Slog.e(TAG, "Agent threw during creation: " + e);
2795                    if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE
2796                            && data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE_FULL) {
2797                        throw e;
2798                    }
2799                    // falling through with 'binder' still null
2800                }
2801            }
2802
2803            // tell the OS that we're live now
2804            try {
2805                ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder);
2806            } catch (RemoteException e) {
2807                // nothing to do.
2808            }
2809        } catch (Exception e) {
2810            throw new RuntimeException("Unable to create BackupAgent "
2811                    + classname + ": " + e.toString(), e);
2812        }
2813    }
2814
2815    // Tear down a BackupAgent
2816    private void handleDestroyBackupAgent(CreateBackupAgentData data) {
2817        if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
2818
2819        LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
2820        String packageName = packageInfo.mPackageName;
2821        BackupAgent agent = mBackupAgents.get(packageName);
2822        if (agent != null) {
2823            try {
2824                agent.onDestroy();
2825            } catch (Exception e) {
2826                Slog.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo);
2827                e.printStackTrace();
2828            }
2829            mBackupAgents.remove(packageName);
2830        } else {
2831            Slog.w(TAG, "Attempt to destroy unknown backup agent " + data);
2832        }
2833    }
2834
2835    private void handleCreateService(CreateServiceData data) {
2836        // If we are getting ready to gc after going to the background, well
2837        // we are back active so skip it.
2838        unscheduleGcIdler();
2839
2840        LoadedApk packageInfo = getPackageInfoNoCheck(
2841                data.info.applicationInfo, data.compatInfo);
2842        Service service = null;
2843        try {
2844            java.lang.ClassLoader cl = packageInfo.getClassLoader();
2845            service = (Service) cl.loadClass(data.info.name).newInstance();
2846        } catch (Exception e) {
2847            if (!mInstrumentation.onException(service, e)) {
2848                throw new RuntimeException(
2849                    "Unable to instantiate service " + data.info.name
2850                    + ": " + e.toString(), e);
2851            }
2852        }
2853
2854        try {
2855            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
2856
2857            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
2858            context.setOuterContext(service);
2859
2860            Application app = packageInfo.makeApplication(false, mInstrumentation);
2861            service.attach(context, this, data.info.name, data.token, app,
2862                    ActivityManagerNative.getDefault());
2863            service.onCreate();
2864            mServices.put(data.token, service);
2865            try {
2866                ActivityManagerNative.getDefault().serviceDoneExecuting(
2867                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
2868            } catch (RemoteException e) {
2869                // nothing to do.
2870            }
2871        } catch (Exception e) {
2872            if (!mInstrumentation.onException(service, e)) {
2873                throw new RuntimeException(
2874                    "Unable to create service " + data.info.name
2875                    + ": " + e.toString(), e);
2876            }
2877        }
2878    }
2879
2880    private void handleBindService(BindServiceData data) {
2881        Service s = mServices.get(data.token);
2882        if (DEBUG_SERVICE)
2883            Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
2884        if (s != null) {
2885            try {
2886                data.intent.setExtrasClassLoader(s.getClassLoader());
2887                data.intent.prepareToEnterProcess();
2888                try {
2889                    if (!data.rebind) {
2890                        IBinder binder = s.onBind(data.intent);
2891                        ActivityManagerNative.getDefault().publishService(
2892                                data.token, data.intent, binder);
2893                    } else {
2894                        s.onRebind(data.intent);
2895                        ActivityManagerNative.getDefault().serviceDoneExecuting(
2896                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
2897                    }
2898                    ensureJitEnabled();
2899                } catch (RemoteException ex) {
2900                }
2901            } catch (Exception e) {
2902                if (!mInstrumentation.onException(s, e)) {
2903                    throw new RuntimeException(
2904                            "Unable to bind to service " + s
2905                            + " with " + data.intent + ": " + e.toString(), e);
2906                }
2907            }
2908        }
2909    }
2910
2911    private void handleUnbindService(BindServiceData data) {
2912        Service s = mServices.get(data.token);
2913        if (s != null) {
2914            try {
2915                data.intent.setExtrasClassLoader(s.getClassLoader());
2916                data.intent.prepareToEnterProcess();
2917                boolean doRebind = s.onUnbind(data.intent);
2918                try {
2919                    if (doRebind) {
2920                        ActivityManagerNative.getDefault().unbindFinished(
2921                                data.token, data.intent, doRebind);
2922                    } else {
2923                        ActivityManagerNative.getDefault().serviceDoneExecuting(
2924                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
2925                    }
2926                } catch (RemoteException ex) {
2927                }
2928            } catch (Exception e) {
2929                if (!mInstrumentation.onException(s, e)) {
2930                    throw new RuntimeException(
2931                            "Unable to unbind to service " + s
2932                            + " with " + data.intent + ": " + e.toString(), e);
2933                }
2934            }
2935        }
2936    }
2937
2938    private void handleDumpService(DumpComponentInfo info) {
2939        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
2940        try {
2941            Service s = mServices.get(info.token);
2942            if (s != null) {
2943                PrintWriter pw = new FastPrintWriter(new FileOutputStream(
2944                        info.fd.getFileDescriptor()));
2945                s.dump(info.fd.getFileDescriptor(), pw, info.args);
2946                pw.flush();
2947            }
2948        } finally {
2949            IoUtils.closeQuietly(info.fd);
2950            StrictMode.setThreadPolicy(oldPolicy);
2951        }
2952    }
2953
2954    private void handleDumpActivity(DumpComponentInfo info) {
2955        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
2956        try {
2957            ActivityClientRecord r = mActivities.get(info.token);
2958            if (r != null && r.activity != null) {
2959                PrintWriter pw = new FastPrintWriter(new FileOutputStream(
2960                        info.fd.getFileDescriptor()));
2961                r.activity.dump(info.prefix, info.fd.getFileDescriptor(), pw, info.args);
2962                pw.flush();
2963            }
2964        } finally {
2965            IoUtils.closeQuietly(info.fd);
2966            StrictMode.setThreadPolicy(oldPolicy);
2967        }
2968    }
2969
2970    private void handleDumpProvider(DumpComponentInfo info) {
2971        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
2972        try {
2973            ProviderClientRecord r = mLocalProviders.get(info.token);
2974            if (r != null && r.mLocalProvider != null) {
2975                PrintWriter pw = new FastPrintWriter(new FileOutputStream(
2976                        info.fd.getFileDescriptor()));
2977                r.mLocalProvider.dump(info.fd.getFileDescriptor(), pw, info.args);
2978                pw.flush();
2979            }
2980        } finally {
2981            IoUtils.closeQuietly(info.fd);
2982            StrictMode.setThreadPolicy(oldPolicy);
2983        }
2984    }
2985
2986    private void handleServiceArgs(ServiceArgsData data) {
2987        Service s = mServices.get(data.token);
2988        if (s != null) {
2989            try {
2990                if (data.args != null) {
2991                    data.args.setExtrasClassLoader(s.getClassLoader());
2992                    data.args.prepareToEnterProcess();
2993                }
2994                int res;
2995                if (!data.taskRemoved) {
2996                    res = s.onStartCommand(data.args, data.flags, data.startId);
2997                } else {
2998                    s.onTaskRemoved(data.args);
2999                    res = Service.START_TASK_REMOVED_COMPLETE;
3000                }
3001
3002                QueuedWork.waitToFinish();
3003
3004                try {
3005                    ActivityManagerNative.getDefault().serviceDoneExecuting(
3006                            data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
3007                } catch (RemoteException e) {
3008                    // nothing to do.
3009                }
3010                ensureJitEnabled();
3011            } catch (Exception e) {
3012                if (!mInstrumentation.onException(s, e)) {
3013                    throw new RuntimeException(
3014                            "Unable to start service " + s
3015                            + " with " + data.args + ": " + e.toString(), e);
3016                }
3017            }
3018        }
3019    }
3020
3021    private void handleStopService(IBinder token) {
3022        Service s = mServices.remove(token);
3023        if (s != null) {
3024            try {
3025                if (localLOGV) Slog.v(TAG, "Destroying service " + s);
3026                s.onDestroy();
3027                Context context = s.getBaseContext();
3028                if (context instanceof ContextImpl) {
3029                    final String who = s.getClassName();
3030                    ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
3031                }
3032
3033                QueuedWork.waitToFinish();
3034
3035                try {
3036                    ActivityManagerNative.getDefault().serviceDoneExecuting(
3037                            token, SERVICE_DONE_EXECUTING_STOP, 0, 0);
3038                } catch (RemoteException e) {
3039                    // nothing to do.
3040                    Slog.i(TAG, "handleStopService: unable to execute serviceDoneExecuting for "
3041                            + token, e);
3042                }
3043            } catch (Exception e) {
3044                if (!mInstrumentation.onException(s, e)) {
3045                    throw new RuntimeException(
3046                            "Unable to stop service " + s
3047                            + ": " + e.toString(), e);
3048                }
3049                Slog.i(TAG, "handleStopService: exception for " + token, e);
3050            }
3051        } else {
3052            Slog.i(TAG, "handleStopService: token=" + token + " not found.");
3053        }
3054        //Slog.i(TAG, "Running services: " + mServices);
3055    }
3056
3057    public final ActivityClientRecord performResumeActivity(IBinder token,
3058            boolean clearHide) {
3059        ActivityClientRecord r = mActivities.get(token);
3060        if (localLOGV) Slog.v(TAG, "Performing resume of " + r
3061                + " finished=" + r.activity.mFinished);
3062        if (r != null && !r.activity.mFinished) {
3063            if (clearHide) {
3064                r.hideForNow = false;
3065                r.activity.mStartedActivity = false;
3066            }
3067            try {
3068                r.activity.mFragments.noteStateNotSaved();
3069                if (r.pendingIntents != null) {
3070                    deliverNewIntents(r, r.pendingIntents);
3071                    r.pendingIntents = null;
3072                }
3073                if (r.pendingResults != null) {
3074                    deliverResults(r, r.pendingResults);
3075                    r.pendingResults = null;
3076                }
3077                r.activity.performResume();
3078
3079                EventLog.writeEvent(LOG_AM_ON_RESUME_CALLED,
3080                        UserHandle.myUserId(), r.activity.getComponentName().getClassName());
3081
3082                r.paused = false;
3083                r.stopped = false;
3084                r.state = null;
3085                r.persistentState = null;
3086            } catch (Exception e) {
3087                if (!mInstrumentation.onException(r.activity, e)) {
3088                    throw new RuntimeException(
3089                        "Unable to resume activity "
3090                        + r.intent.getComponent().toShortString()
3091                        + ": " + e.toString(), e);
3092                }
3093            }
3094        }
3095        return r;
3096    }
3097
3098    static final void cleanUpPendingRemoveWindows(ActivityClientRecord r) {
3099        if (r.mPendingRemoveWindow != null) {
3100            r.mPendingRemoveWindowManager.removeViewImmediate(r.mPendingRemoveWindow);
3101            IBinder wtoken = r.mPendingRemoveWindow.getWindowToken();
3102            if (wtoken != null) {
3103                WindowManagerGlobal.getInstance().closeAll(wtoken,
3104                        r.activity.getClass().getName(), "Activity");
3105            }
3106        }
3107        r.mPendingRemoveWindow = null;
3108        r.mPendingRemoveWindowManager = null;
3109    }
3110
3111    final void handleResumeActivity(IBinder token,
3112            boolean clearHide, boolean isForward, boolean reallyResume) {
3113        // If we are getting ready to gc after going to the background, well
3114        // we are back active so skip it.
3115        unscheduleGcIdler();
3116        mSomeActivitiesChanged = true;
3117
3118        // TODO Push resumeArgs into the activity for consideration
3119        ActivityClientRecord r = performResumeActivity(token, clearHide);
3120
3121        if (r != null) {
3122            final Activity a = r.activity;
3123
3124            if (localLOGV) Slog.v(
3125                TAG, "Resume " + r + " started activity: " +
3126                a.mStartedActivity + ", hideForNow: " + r.hideForNow
3127                + ", finished: " + a.mFinished);
3128
3129            final int forwardBit = isForward ?
3130                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
3131
3132            // If the window hasn't yet been added to the window manager,
3133            // and this guy didn't finish itself or start another activity,
3134            // then go ahead and add the window.
3135            boolean willBeVisible = !a.mStartedActivity;
3136            if (!willBeVisible) {
3137                try {
3138                    willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
3139                            a.getActivityToken());
3140                } catch (RemoteException e) {
3141                }
3142            }
3143            if (r.window == null && !a.mFinished && willBeVisible) {
3144                r.window = r.activity.getWindow();
3145                View decor = r.window.getDecorView();
3146                decor.setVisibility(View.INVISIBLE);
3147                ViewManager wm = a.getWindowManager();
3148                WindowManager.LayoutParams l = r.window.getAttributes();
3149                a.mDecor = decor;
3150                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
3151                l.softInputMode |= forwardBit;
3152                if (a.mVisibleFromClient) {
3153                    a.mWindowAdded = true;
3154                    wm.addView(decor, l);
3155                }
3156
3157            // If the window has already been added, but during resume
3158            // we started another activity, then don't yet make the
3159            // window visible.
3160            } else if (!willBeVisible) {
3161                if (localLOGV) Slog.v(
3162                    TAG, "Launch " + r + " mStartedActivity set");
3163                r.hideForNow = true;
3164            }
3165
3166            // Get rid of anything left hanging around.
3167            cleanUpPendingRemoveWindows(r);
3168
3169            // The window is now visible if it has been added, we are not
3170            // simply finishing, and we are not starting another activity.
3171            if (!r.activity.mFinished && willBeVisible
3172                    && r.activity.mDecor != null && !r.hideForNow) {
3173                if (r.newConfig != null) {
3174                    r.tmpConfig.setTo(r.newConfig);
3175                    if (r.overrideConfig != null) {
3176                        r.tmpConfig.updateFrom(r.overrideConfig);
3177                    }
3178                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
3179                            + r.activityInfo.name + " with newConfig " + r.tmpConfig);
3180                    performConfigurationChanged(r.activity, r.tmpConfig);
3181                    freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
3182                    r.newConfig = null;
3183                }
3184                if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
3185                        + isForward);
3186                WindowManager.LayoutParams l = r.window.getAttributes();
3187                if ((l.softInputMode
3188                        & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
3189                        != forwardBit) {
3190                    l.softInputMode = (l.softInputMode
3191                            & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
3192                            | forwardBit;
3193                    if (r.activity.mVisibleFromClient) {
3194                        ViewManager wm = a.getWindowManager();
3195                        View decor = r.window.getDecorView();
3196                        wm.updateViewLayout(decor, l);
3197                    }
3198                }
3199                r.activity.mVisibleFromServer = true;
3200                mNumVisibleActivities++;
3201                if (r.activity.mVisibleFromClient) {
3202                    r.activity.makeVisible();
3203                }
3204            }
3205
3206            if (!r.onlyLocalRequest) {
3207                r.nextIdle = mNewActivities;
3208                mNewActivities = r;
3209                if (localLOGV) Slog.v(
3210                    TAG, "Scheduling idle handler for " + r);
3211                Looper.myQueue().addIdleHandler(new Idler());
3212            }
3213            r.onlyLocalRequest = false;
3214
3215            // Tell the activity manager we have resumed.
3216            if (reallyResume) {
3217                try {
3218                    ActivityManagerNative.getDefault().activityResumed(token);
3219                } catch (RemoteException ex) {
3220                }
3221            }
3222
3223        } else {
3224            // If an exception was thrown when trying to resume, then
3225            // just end this activity.
3226            try {
3227                ActivityManagerNative.getDefault()
3228                    .finishActivity(token, Activity.RESULT_CANCELED, null, false);
3229            } catch (RemoteException ex) {
3230            }
3231        }
3232    }
3233
3234    private int mThumbnailWidth = -1;
3235    private int mThumbnailHeight = -1;
3236    private Bitmap mAvailThumbnailBitmap = null;
3237    private Canvas mThumbnailCanvas = null;
3238
3239    private Bitmap createThumbnailBitmap(ActivityClientRecord r) {
3240        Bitmap thumbnail = mAvailThumbnailBitmap;
3241        try {
3242            if (thumbnail == null) {
3243                int w = mThumbnailWidth;
3244                int h;
3245                if (w < 0) {
3246                    Resources res = r.activity.getResources();
3247                    int wId = com.android.internal.R.dimen.thumbnail_width;
3248                    int hId = com.android.internal.R.dimen.thumbnail_height;
3249                    mThumbnailWidth = w = res.getDimensionPixelSize(wId);
3250                    mThumbnailHeight = h = res.getDimensionPixelSize(hId);
3251                } else {
3252                    h = mThumbnailHeight;
3253                }
3254
3255                // On platforms where we don't want thumbnails, set dims to (0,0)
3256                if ((w > 0) && (h > 0)) {
3257                    thumbnail = Bitmap.createBitmap(r.activity.getResources().getDisplayMetrics(),
3258                            w, h, THUMBNAIL_FORMAT);
3259                    thumbnail.eraseColor(0);
3260                }
3261            }
3262
3263            if (thumbnail != null) {
3264                Canvas cv = mThumbnailCanvas;
3265                if (cv == null) {
3266                    mThumbnailCanvas = cv = new Canvas();
3267                }
3268
3269                cv.setBitmap(thumbnail);
3270                if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
3271                    mAvailThumbnailBitmap = thumbnail;
3272                    thumbnail = null;
3273                }
3274                cv.setBitmap(null);
3275            }
3276
3277        } catch (Exception e) {
3278            if (!mInstrumentation.onException(r.activity, e)) {
3279                throw new RuntimeException(
3280                        "Unable to create thumbnail of "
3281                        + r.intent.getComponent().toShortString()
3282                        + ": " + e.toString(), e);
3283            }
3284            thumbnail = null;
3285        }
3286
3287        return thumbnail;
3288    }
3289
3290    private void handlePauseActivity(IBinder token, boolean finished,
3291            boolean userLeaving, int configChanges, boolean dontReport) {
3292        ActivityClientRecord r = mActivities.get(token);
3293        if (r != null) {
3294            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
3295            if (userLeaving) {
3296                performUserLeavingActivity(r);
3297            }
3298
3299            r.activity.mConfigChangeFlags |= configChanges;
3300            performPauseActivity(token, finished, r.isPreHoneycomb());
3301
3302            // Make sure any pending writes are now committed.
3303            if (r.isPreHoneycomb()) {
3304                QueuedWork.waitToFinish();
3305            }
3306
3307            // Tell the activity manager we have paused.
3308            if (!dontReport) {
3309                try {
3310                    ActivityManagerNative.getDefault().activityPaused(token);
3311                } catch (RemoteException ex) {
3312                }
3313            }
3314            mSomeActivitiesChanged = true;
3315        }
3316    }
3317
3318    final void performUserLeavingActivity(ActivityClientRecord r) {
3319        mInstrumentation.callActivityOnUserLeaving(r.activity);
3320    }
3321
3322    final Bundle performPauseActivity(IBinder token, boolean finished,
3323            boolean saveState) {
3324        ActivityClientRecord r = mActivities.get(token);
3325        return r != null ? performPauseActivity(r, finished, saveState) : null;
3326    }
3327
3328    final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
3329            boolean saveState) {
3330        if (r.paused) {
3331            if (r.activity.mFinished) {
3332                // If we are finishing, we won't call onResume() in certain cases.
3333                // So here we likewise don't want to call onPause() if the activity
3334                // isn't resumed.
3335                return null;
3336            }
3337            RuntimeException e = new RuntimeException(
3338                    "Performing pause of activity that is not resumed: "
3339                    + r.intent.getComponent().toShortString());
3340            Slog.e(TAG, e.getMessage(), e);
3341        }
3342        if (finished) {
3343            r.activity.mFinished = true;
3344        }
3345        try {
3346            // Next have the activity save its current state and managed dialogs...
3347            if (!r.activity.mFinished && saveState) {
3348                callCallActivityOnSaveInstanceState(r);
3349            }
3350            // Now we are idle.
3351            r.activity.mCalled = false;
3352            mInstrumentation.callActivityOnPause(r.activity);
3353            EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
3354                    r.activity.getComponentName().getClassName());
3355            if (!r.activity.mCalled) {
3356                throw new SuperNotCalledException(
3357                    "Activity " + r.intent.getComponent().toShortString() +
3358                    " did not call through to super.onPause()");
3359            }
3360
3361        } catch (SuperNotCalledException e) {
3362            throw e;
3363
3364        } catch (Exception e) {
3365            if (!mInstrumentation.onException(r.activity, e)) {
3366                throw new RuntimeException(
3367                        "Unable to pause activity "
3368                        + r.intent.getComponent().toShortString()
3369                        + ": " + e.toString(), e);
3370            }
3371        }
3372        r.paused = true;
3373
3374        // Notify any outstanding on paused listeners
3375        ArrayList<OnActivityPausedListener> listeners;
3376        synchronized (mOnPauseListeners) {
3377            listeners = mOnPauseListeners.remove(r.activity);
3378        }
3379        int size = (listeners != null ? listeners.size() : 0);
3380        for (int i = 0; i < size; i++) {
3381            listeners.get(i).onPaused(r.activity);
3382        }
3383
3384        return !r.activity.mFinished && saveState ? r.state : null;
3385    }
3386
3387    final void performStopActivity(IBinder token, boolean saveState) {
3388        ActivityClientRecord r = mActivities.get(token);
3389        performStopActivityInner(r, null, false, saveState);
3390    }
3391
3392    private static class StopInfo implements Runnable {
3393        ActivityClientRecord activity;
3394        Bundle state;
3395        PersistableBundle persistentState;
3396        CharSequence description;
3397
3398        @Override public void run() {
3399            // Tell activity manager we have been stopped.
3400            try {
3401                if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Reporting activity stopped: " + activity);
3402                ActivityManagerNative.getDefault().activityStopped(
3403                    activity.token, state, persistentState, description);
3404            } catch (RemoteException ex) {
3405            }
3406        }
3407    }
3408
3409    private static final class ProviderRefCount {
3410        public final IActivityManager.ContentProviderHolder holder;
3411        public final ProviderClientRecord client;
3412        public int stableCount;
3413        public int unstableCount;
3414
3415        // When this is set, the stable and unstable ref counts are 0 and
3416        // we have a pending operation scheduled to remove the ref count
3417        // from the activity manager.  On the activity manager we are still
3418        // holding an unstable ref, though it is not reflected in the counts
3419        // here.
3420        public boolean removePending;
3421
3422        ProviderRefCount(IActivityManager.ContentProviderHolder inHolder,
3423                ProviderClientRecord inClient, int sCount, int uCount) {
3424            holder = inHolder;
3425            client = inClient;
3426            stableCount = sCount;
3427            unstableCount = uCount;
3428        }
3429    }
3430
3431    /**
3432     * Core implementation of stopping an activity.  Note this is a little
3433     * tricky because the server's meaning of stop is slightly different
3434     * than our client -- for the server, stop means to save state and give
3435     * it the result when it is done, but the window may still be visible.
3436     * For the client, we want to call onStop()/onStart() to indicate when
3437     * the activity's UI visibillity changes.
3438     */
3439    private void performStopActivityInner(ActivityClientRecord r,
3440            StopInfo info, boolean keepShown, boolean saveState) {
3441        if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
3442        if (r != null) {
3443            if (!keepShown && r.stopped) {
3444                if (r.activity.mFinished) {
3445                    // If we are finishing, we won't call onResume() in certain
3446                    // cases.  So here we likewise don't want to call onStop()
3447                    // if the activity isn't resumed.
3448                    return;
3449                }
3450                RuntimeException e = new RuntimeException(
3451                        "Performing stop of activity that is not resumed: "
3452                        + r.intent.getComponent().toShortString());
3453                Slog.e(TAG, e.getMessage(), e);
3454            }
3455
3456            if (info != null) {
3457                try {
3458                    // First create a thumbnail for the activity...
3459                    // For now, don't create the thumbnail here; we are
3460                    // doing that by doing a screen snapshot.
3461                    info.description = r.activity.onCreateDescription();
3462                } catch (Exception e) {
3463                    if (!mInstrumentation.onException(r.activity, e)) {
3464                        throw new RuntimeException(
3465                                "Unable to save state of activity "
3466                                + r.intent.getComponent().toShortString()
3467                                + ": " + e.toString(), e);
3468                    }
3469                }
3470            }
3471
3472            // Next have the activity save its current state and managed dialogs...
3473            if (!r.activity.mFinished && saveState) {
3474                if (r.state == null) {
3475                    callCallActivityOnSaveInstanceState(r);
3476                }
3477            }
3478
3479            if (!keepShown) {
3480                try {
3481                    // Now we are idle.
3482                    r.activity.performStop();
3483                } catch (Exception e) {
3484                    if (!mInstrumentation.onException(r.activity, e)) {
3485                        throw new RuntimeException(
3486                                "Unable to stop activity "
3487                                + r.intent.getComponent().toShortString()
3488                                + ": " + e.toString(), e);
3489                    }
3490                }
3491                r.stopped = true;
3492            }
3493
3494            r.paused = true;
3495        }
3496    }
3497
3498    private void updateVisibility(ActivityClientRecord r, boolean show) {
3499        View v = r.activity.mDecor;
3500        if (v != null) {
3501            if (show) {
3502                if (!r.activity.mVisibleFromServer) {
3503                    r.activity.mVisibleFromServer = true;
3504                    mNumVisibleActivities++;
3505                    if (r.activity.mVisibleFromClient) {
3506                        r.activity.makeVisible();
3507                    }
3508                }
3509                if (r.newConfig != null) {
3510                    r.tmpConfig.setTo(r.newConfig);
3511                    if (r.overrideConfig != null) {
3512                        r.tmpConfig.updateFrom(r.overrideConfig);
3513                    }
3514                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
3515                            + r.activityInfo.name + " with new config " + r.tmpConfig);
3516                    performConfigurationChanged(r.activity, r.tmpConfig);
3517                    freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
3518                    r.newConfig = null;
3519                }
3520            } else {
3521                if (r.activity.mVisibleFromServer) {
3522                    r.activity.mVisibleFromServer = false;
3523                    mNumVisibleActivities--;
3524                    v.setVisibility(View.INVISIBLE);
3525                }
3526            }
3527        }
3528    }
3529
3530    private void handleStopActivity(IBinder token, boolean show, int configChanges) {
3531        ActivityClientRecord r = mActivities.get(token);
3532        r.activity.mConfigChangeFlags |= configChanges;
3533
3534        StopInfo info = new StopInfo();
3535        performStopActivityInner(r, info, show, true);
3536
3537        if (localLOGV) Slog.v(
3538            TAG, "Finishing stop of " + r + ": show=" + show
3539            + " win=" + r.window);
3540
3541        updateVisibility(r, show);
3542
3543        // Make sure any pending writes are now committed.
3544        if (!r.isPreHoneycomb()) {
3545            QueuedWork.waitToFinish();
3546        }
3547
3548        // Schedule the call to tell the activity manager we have
3549        // stopped.  We don't do this immediately, because we want to
3550        // have a chance for any other pending work (in particular memory
3551        // trim requests) to complete before you tell the activity
3552        // manager to proceed and allow us to go fully into the background.
3553        info.activity = r;
3554        info.state = r.state;
3555        info.persistentState = r.persistentState;
3556        mH.post(info);
3557        mSomeActivitiesChanged = true;
3558    }
3559
3560    final void performRestartActivity(IBinder token) {
3561        ActivityClientRecord r = mActivities.get(token);
3562        if (r.stopped) {
3563            r.activity.performRestart();
3564            r.stopped = false;
3565        }
3566    }
3567
3568    private void handleWindowVisibility(IBinder token, boolean show) {
3569        ActivityClientRecord r = mActivities.get(token);
3570
3571        if (r == null) {
3572            Log.w(TAG, "handleWindowVisibility: no activity for token " + token);
3573            return;
3574        }
3575
3576        if (!show && !r.stopped) {
3577            performStopActivityInner(r, null, show, false);
3578        } else if (show && r.stopped) {
3579            // If we are getting ready to gc after going to the background, well
3580            // we are back active so skip it.
3581            unscheduleGcIdler();
3582
3583            r.activity.performRestart();
3584            r.stopped = false;
3585        }
3586        if (r.activity.mDecor != null) {
3587            if (false) Slog.v(
3588                TAG, "Handle window " + r + " visibility: " + show);
3589            updateVisibility(r, show);
3590        }
3591        mSomeActivitiesChanged = true;
3592    }
3593
3594    private void handleSleeping(IBinder token, boolean sleeping) {
3595        ActivityClientRecord r = mActivities.get(token);
3596
3597        if (r == null) {
3598            Log.w(TAG, "handleSleeping: no activity for token " + token);
3599            return;
3600        }
3601
3602        if (sleeping) {
3603            if (!r.stopped && !r.isPreHoneycomb()) {
3604                try {
3605                    // Now we are idle.
3606                    r.activity.performStop();
3607                } catch (Exception e) {
3608                    if (!mInstrumentation.onException(r.activity, e)) {
3609                        throw new RuntimeException(
3610                                "Unable to stop activity "
3611                                + r.intent.getComponent().toShortString()
3612                                + ": " + e.toString(), e);
3613                    }
3614                }
3615                r.stopped = true;
3616            }
3617
3618            // Make sure any pending writes are now committed.
3619            if (!r.isPreHoneycomb()) {
3620                QueuedWork.waitToFinish();
3621            }
3622
3623            // Tell activity manager we slept.
3624            try {
3625                ActivityManagerNative.getDefault().activitySlept(r.token);
3626            } catch (RemoteException ex) {
3627            }
3628        } else {
3629            if (r.stopped && r.activity.mVisibleFromServer) {
3630                r.activity.performRestart();
3631                r.stopped = false;
3632            }
3633        }
3634    }
3635
3636    private void handleSetCoreSettings(Bundle coreSettings) {
3637        synchronized (mResourcesManager) {
3638            mCoreSettings = coreSettings;
3639        }
3640        onCoreSettingsChange();
3641    }
3642
3643    private void onCoreSettingsChange() {
3644        boolean debugViewAttributes =
3645                mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;
3646        if (debugViewAttributes != View.mDebugViewAttributes) {
3647            View.mDebugViewAttributes = debugViewAttributes;
3648
3649            // request all activities to relaunch for the changes to take place
3650            for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
3651                requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, null, false);
3652            }
3653        }
3654    }
3655
3656    private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) {
3657        LoadedApk apk = peekPackageInfo(data.pkg, false);
3658        if (apk != null) {
3659            apk.setCompatibilityInfo(data.info);
3660        }
3661        apk = peekPackageInfo(data.pkg, true);
3662        if (apk != null) {
3663            apk.setCompatibilityInfo(data.info);
3664        }
3665        handleConfigurationChanged(mConfiguration, data.info);
3666        WindowManagerGlobal.getInstance().reportNewConfiguration(mConfiguration);
3667    }
3668
3669    private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
3670        final int N = results.size();
3671        for (int i=0; i<N; i++) {
3672            ResultInfo ri = results.get(i);
3673            try {
3674                if (ri.mData != null) {
3675                    ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
3676                    ri.mData.prepareToEnterProcess();
3677                }
3678                if (DEBUG_RESULTS) Slog.v(TAG,
3679                        "Delivering result to activity " + r + " : " + ri);
3680                r.activity.dispatchActivityResult(ri.mResultWho,
3681                        ri.mRequestCode, ri.mResultCode, ri.mData);
3682            } catch (Exception e) {
3683                if (!mInstrumentation.onException(r.activity, e)) {
3684                    throw new RuntimeException(
3685                            "Failure delivering result " + ri + " to activity "
3686                            + r.intent.getComponent().toShortString()
3687                            + ": " + e.toString(), e);
3688                }
3689            }
3690        }
3691    }
3692
3693    private void handleSendResult(ResultData res) {
3694        ActivityClientRecord r = mActivities.get(res.token);
3695        if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
3696        if (r != null) {
3697            final boolean resumed = !r.paused;
3698            if (!r.activity.mFinished && r.activity.mDecor != null
3699                    && r.hideForNow && resumed) {
3700                // We had hidden the activity because it started another
3701                // one...  we have gotten a result back and we are not
3702                // paused, so make sure our window is visible.
3703                updateVisibility(r, true);
3704            }
3705            if (resumed) {
3706                try {
3707                    // Now we are idle.
3708                    r.activity.mCalled = false;
3709                    r.activity.mTemporaryPause = true;
3710                    mInstrumentation.callActivityOnPause(r.activity);
3711                    if (!r.activity.mCalled) {
3712                        throw new SuperNotCalledException(
3713                            "Activity " + r.intent.getComponent().toShortString()
3714                            + " did not call through to super.onPause()");
3715                    }
3716                } catch (SuperNotCalledException e) {
3717                    throw e;
3718                } catch (Exception e) {
3719                    if (!mInstrumentation.onException(r.activity, e)) {
3720                        throw new RuntimeException(
3721                                "Unable to pause activity "
3722                                + r.intent.getComponent().toShortString()
3723                                + ": " + e.toString(), e);
3724                    }
3725                }
3726            }
3727            deliverResults(r, res.results);
3728            if (resumed) {
3729                r.activity.performResume();
3730                r.activity.mTemporaryPause = false;
3731            }
3732        }
3733    }
3734
3735    public final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing) {
3736        return performDestroyActivity(token, finishing, 0, false);
3737    }
3738
3739    private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
3740            int configChanges, boolean getNonConfigInstance) {
3741        ActivityClientRecord r = mActivities.get(token);
3742        Class<? extends Activity> activityClass = null;
3743        if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
3744        if (r != null) {
3745            activityClass = r.activity.getClass();
3746            r.activity.mConfigChangeFlags |= configChanges;
3747            if (finishing) {
3748                r.activity.mFinished = true;
3749            }
3750            if (!r.paused) {
3751                try {
3752                    r.activity.mCalled = false;
3753                    mInstrumentation.callActivityOnPause(r.activity);
3754                    EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
3755                            r.activity.getComponentName().getClassName());
3756                    if (!r.activity.mCalled) {
3757                        throw new SuperNotCalledException(
3758                            "Activity " + safeToComponentShortString(r.intent)
3759                            + " did not call through to super.onPause()");
3760                    }
3761                } catch (SuperNotCalledException e) {
3762                    throw e;
3763                } catch (Exception e) {
3764                    if (!mInstrumentation.onException(r.activity, e)) {
3765                        throw new RuntimeException(
3766                                "Unable to pause activity "
3767                                + safeToComponentShortString(r.intent)
3768                                + ": " + e.toString(), e);
3769                    }
3770                }
3771                r.paused = true;
3772            }
3773            if (!r.stopped) {
3774                try {
3775                    r.activity.performStop();
3776                } catch (SuperNotCalledException e) {
3777                    throw e;
3778                } catch (Exception e) {
3779                    if (!mInstrumentation.onException(r.activity, e)) {
3780                        throw new RuntimeException(
3781                                "Unable to stop activity "
3782                                + safeToComponentShortString(r.intent)
3783                                + ": " + e.toString(), e);
3784                    }
3785                }
3786                r.stopped = true;
3787            }
3788            if (getNonConfigInstance) {
3789                try {
3790                    r.lastNonConfigurationInstances
3791                            = r.activity.retainNonConfigurationInstances();
3792                } catch (Exception e) {
3793                    if (!mInstrumentation.onException(r.activity, e)) {
3794                        throw new RuntimeException(
3795                                "Unable to retain activity "
3796                                + r.intent.getComponent().toShortString()
3797                                + ": " + e.toString(), e);
3798                    }
3799                }
3800            }
3801            try {
3802                r.activity.mCalled = false;
3803                mInstrumentation.callActivityOnDestroy(r.activity);
3804                if (!r.activity.mCalled) {
3805                    throw new SuperNotCalledException(
3806                        "Activity " + safeToComponentShortString(r.intent) +
3807                        " did not call through to super.onDestroy()");
3808                }
3809                if (r.window != null) {
3810                    r.window.closeAllPanels();
3811                }
3812            } catch (SuperNotCalledException e) {
3813                throw e;
3814            } catch (Exception e) {
3815                if (!mInstrumentation.onException(r.activity, e)) {
3816                    throw new RuntimeException(
3817                            "Unable to destroy activity " + safeToComponentShortString(r.intent)
3818                            + ": " + e.toString(), e);
3819                }
3820            }
3821        }
3822        mActivities.remove(token);
3823        StrictMode.decrementExpectedActivityCount(activityClass);
3824        return r;
3825    }
3826
3827    private static String safeToComponentShortString(Intent intent) {
3828        ComponentName component = intent.getComponent();
3829        return component == null ? "[Unknown]" : component.toShortString();
3830    }
3831
3832    private void handleDestroyActivity(IBinder token, boolean finishing,
3833            int configChanges, boolean getNonConfigInstance) {
3834        ActivityClientRecord r = performDestroyActivity(token, finishing,
3835                configChanges, getNonConfigInstance);
3836        if (r != null) {
3837            cleanUpPendingRemoveWindows(r);
3838            WindowManager wm = r.activity.getWindowManager();
3839            View v = r.activity.mDecor;
3840            if (v != null) {
3841                if (r.activity.mVisibleFromServer) {
3842                    mNumVisibleActivities--;
3843                }
3844                IBinder wtoken = v.getWindowToken();
3845                if (r.activity.mWindowAdded) {
3846                    if (r.onlyLocalRequest) {
3847                        // Hold off on removing this until the new activity's
3848                        // window is being added.
3849                        r.mPendingRemoveWindow = v;
3850                        r.mPendingRemoveWindowManager = wm;
3851                    } else {
3852                        wm.removeViewImmediate(v);
3853                    }
3854                }
3855                if (wtoken != null && r.mPendingRemoveWindow == null) {
3856                    WindowManagerGlobal.getInstance().closeAll(wtoken,
3857                            r.activity.getClass().getName(), "Activity");
3858                }
3859                r.activity.mDecor = null;
3860            }
3861            if (r.mPendingRemoveWindow == null) {
3862                // If we are delaying the removal of the activity window, then
3863                // we can't clean up all windows here.  Note that we can't do
3864                // so later either, which means any windows that aren't closed
3865                // by the app will leak.  Well we try to warning them a lot
3866                // about leaking windows, because that is a bug, so if they are
3867                // using this recreate facility then they get to live with leaks.
3868                WindowManagerGlobal.getInstance().closeAll(token,
3869                        r.activity.getClass().getName(), "Activity");
3870            }
3871
3872            // Mocked out contexts won't be participating in the normal
3873            // process lifecycle, but if we're running with a proper
3874            // ApplicationContext we need to have it tear down things
3875            // cleanly.
3876            Context c = r.activity.getBaseContext();
3877            if (c instanceof ContextImpl) {
3878                ((ContextImpl) c).scheduleFinalCleanup(
3879                        r.activity.getClass().getName(), "Activity");
3880            }
3881        }
3882        if (finishing) {
3883            try {
3884                ActivityManagerNative.getDefault().activityDestroyed(token);
3885            } catch (RemoteException ex) {
3886                // If the system process has died, it's game over for everyone.
3887            }
3888        }
3889        mSomeActivitiesChanged = true;
3890    }
3891
3892    public final void requestRelaunchActivity(IBinder token,
3893            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
3894            int configChanges, boolean notResumed, Configuration config,
3895            Configuration overrideConfig, boolean fromServer) {
3896        ActivityClientRecord target = null;
3897
3898        synchronized (mResourcesManager) {
3899            for (int i=0; i<mRelaunchingActivities.size(); i++) {
3900                ActivityClientRecord r = mRelaunchingActivities.get(i);
3901                if (r.token == token) {
3902                    target = r;
3903                    if (pendingResults != null) {
3904                        if (r.pendingResults != null) {
3905                            r.pendingResults.addAll(pendingResults);
3906                        } else {
3907                            r.pendingResults = pendingResults;
3908                        }
3909                    }
3910                    if (pendingNewIntents != null) {
3911                        if (r.pendingIntents != null) {
3912                            r.pendingIntents.addAll(pendingNewIntents);
3913                        } else {
3914                            r.pendingIntents = pendingNewIntents;
3915                        }
3916                    }
3917                    break;
3918                }
3919            }
3920
3921            if (target == null) {
3922                target = new ActivityClientRecord();
3923                target.token = token;
3924                target.pendingResults = pendingResults;
3925                target.pendingIntents = pendingNewIntents;
3926                if (!fromServer) {
3927                    ActivityClientRecord existing = mActivities.get(token);
3928                    if (existing != null) {
3929                        target.startsNotResumed = existing.paused;
3930                        target.overrideConfig = existing.overrideConfig;
3931                    }
3932                    target.onlyLocalRequest = true;
3933                }
3934                mRelaunchingActivities.add(target);
3935                sendMessage(H.RELAUNCH_ACTIVITY, target);
3936            }
3937
3938            if (fromServer) {
3939                target.startsNotResumed = notResumed;
3940                target.onlyLocalRequest = false;
3941            }
3942            if (config != null) {
3943                target.createdConfig = config;
3944            }
3945            if (overrideConfig != null) {
3946                target.overrideConfig = overrideConfig;
3947            }
3948            target.pendingConfigChanges |= configChanges;
3949        }
3950    }
3951
3952    private void handleRelaunchActivity(ActivityClientRecord tmp) {
3953        // If we are getting ready to gc after going to the background, well
3954        // we are back active so skip it.
3955        unscheduleGcIdler();
3956        mSomeActivitiesChanged = true;
3957
3958        Configuration changedConfig = null;
3959        int configChanges = 0;
3960
3961        // First: make sure we have the most recent configuration and most
3962        // recent version of the activity, or skip it if some previous call
3963        // had taken a more recent version.
3964        synchronized (mResourcesManager) {
3965            int N = mRelaunchingActivities.size();
3966            IBinder token = tmp.token;
3967            tmp = null;
3968            for (int i=0; i<N; i++) {
3969                ActivityClientRecord r = mRelaunchingActivities.get(i);
3970                if (r.token == token) {
3971                    tmp = r;
3972                    configChanges |= tmp.pendingConfigChanges;
3973                    mRelaunchingActivities.remove(i);
3974                    i--;
3975                    N--;
3976                }
3977            }
3978
3979            if (tmp == null) {
3980                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Abort, activity not relaunching!");
3981                return;
3982            }
3983
3984            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
3985                    + tmp.token + " with configChanges=0x"
3986                    + Integer.toHexString(configChanges));
3987
3988            if (mPendingConfiguration != null) {
3989                changedConfig = mPendingConfiguration;
3990                mPendingConfiguration = null;
3991            }
3992        }
3993
3994        if (tmp.createdConfig != null) {
3995            // If the activity manager is passing us its current config,
3996            // assume that is really what we want regardless of what we
3997            // may have pending.
3998            if (mConfiguration == null
3999                    || (tmp.createdConfig.isOtherSeqNewer(mConfiguration)
4000                            && mConfiguration.diff(tmp.createdConfig) != 0)) {
4001                if (changedConfig == null
4002                        || tmp.createdConfig.isOtherSeqNewer(changedConfig)) {
4003                    changedConfig = tmp.createdConfig;
4004                }
4005            }
4006        }
4007
4008        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
4009                + tmp.token + ": changedConfig=" + changedConfig);
4010
4011        // If there was a pending configuration change, execute it first.
4012        if (changedConfig != null) {
4013            mCurDefaultDisplayDpi = changedConfig.densityDpi;
4014            updateDefaultDensity();
4015            handleConfigurationChanged(changedConfig, null);
4016        }
4017
4018        ActivityClientRecord r = mActivities.get(tmp.token);
4019        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r);
4020        if (r == null) {
4021            return;
4022        }
4023
4024        r.activity.mConfigChangeFlags |= configChanges;
4025        r.onlyLocalRequest = tmp.onlyLocalRequest;
4026        Intent currentIntent = r.activity.mIntent;
4027
4028        r.activity.mChangingConfigurations = true;
4029
4030        // Need to ensure state is saved.
4031        if (!r.paused) {
4032            performPauseActivity(r.token, false, r.isPreHoneycomb());
4033        }
4034        if (r.state == null && !r.stopped && !r.isPreHoneycomb()) {
4035            callCallActivityOnSaveInstanceState(r);
4036        }
4037
4038        handleDestroyActivity(r.token, false, configChanges, true);
4039
4040        r.activity = null;
4041        r.window = null;
4042        r.hideForNow = false;
4043        r.nextIdle = null;
4044        // Merge any pending results and pending intents; don't just replace them
4045        if (tmp.pendingResults != null) {
4046            if (r.pendingResults == null) {
4047                r.pendingResults = tmp.pendingResults;
4048            } else {
4049                r.pendingResults.addAll(tmp.pendingResults);
4050            }
4051        }
4052        if (tmp.pendingIntents != null) {
4053            if (r.pendingIntents == null) {
4054                r.pendingIntents = tmp.pendingIntents;
4055            } else {
4056                r.pendingIntents.addAll(tmp.pendingIntents);
4057            }
4058        }
4059        r.startsNotResumed = tmp.startsNotResumed;
4060        r.overrideConfig = tmp.overrideConfig;
4061
4062        handleLaunchActivity(r, currentIntent);
4063    }
4064
4065    private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) {
4066        r.state = new Bundle();
4067        r.state.setAllowFds(false);
4068        if (r.isPersistable()) {
4069            r.persistentState = new PersistableBundle();
4070            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state,
4071                    r.persistentState);
4072        } else {
4073            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
4074        }
4075    }
4076
4077    ArrayList<ComponentCallbacks2> collectComponentCallbacks(
4078            boolean allActivities, Configuration newConfig) {
4079        ArrayList<ComponentCallbacks2> callbacks
4080                = new ArrayList<ComponentCallbacks2>();
4081
4082        synchronized (mResourcesManager) {
4083            final int NAPP = mAllApplications.size();
4084            for (int i=0; i<NAPP; i++) {
4085                callbacks.add(mAllApplications.get(i));
4086            }
4087            final int NACT = mActivities.size();
4088            for (int i=0; i<NACT; i++) {
4089                ActivityClientRecord ar = mActivities.valueAt(i);
4090                Activity a = ar.activity;
4091                if (a != null) {
4092                    Configuration thisConfig = applyConfigCompatMainThread(
4093                            mCurDefaultDisplayDpi, newConfig,
4094                            ar.packageInfo.getCompatibilityInfo());
4095                    if (!ar.activity.mFinished && (allActivities || !ar.paused)) {
4096                        // If the activity is currently resumed, its configuration
4097                        // needs to change right now.
4098                        callbacks.add(a);
4099                    } else if (thisConfig != null) {
4100                        // Otherwise, we will tell it about the change
4101                        // the next time it is resumed or shown.  Note that
4102                        // the activity manager may, before then, decide the
4103                        // activity needs to be destroyed to handle its new
4104                        // configuration.
4105                        if (DEBUG_CONFIGURATION) {
4106                            Slog.v(TAG, "Setting activity "
4107                                    + ar.activityInfo.name + " newConfig=" + thisConfig);
4108                        }
4109                        ar.newConfig = thisConfig;
4110                    }
4111                }
4112            }
4113            final int NSVC = mServices.size();
4114            for (int i=0; i<NSVC; i++) {
4115                callbacks.add(mServices.valueAt(i));
4116            }
4117        }
4118        synchronized (mProviderMap) {
4119            final int NPRV = mLocalProviders.size();
4120            for (int i=0; i<NPRV; i++) {
4121                callbacks.add(mLocalProviders.valueAt(i).mLocalProvider);
4122            }
4123        }
4124
4125        return callbacks;
4126    }
4127
4128    private static void performConfigurationChanged(ComponentCallbacks2 cb, Configuration config) {
4129        // Only for Activity objects, check that they actually call up to their
4130        // superclass implementation.  ComponentCallbacks2 is an interface, so
4131        // we check the runtime type and act accordingly.
4132        Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
4133        if (activity != null) {
4134            activity.mCalled = false;
4135        }
4136
4137        boolean shouldChangeConfig = false;
4138        if ((activity == null) || (activity.mCurrentConfig == null)) {
4139            shouldChangeConfig = true;
4140        } else {
4141
4142            // If the new config is the same as the config this Activity
4143            // is already running with then don't bother calling
4144            // onConfigurationChanged
4145            int diff = activity.mCurrentConfig.diff(config);
4146            if (diff != 0) {
4147                // If this activity doesn't handle any of the config changes
4148                // then don't bother calling onConfigurationChanged as we're
4149                // going to destroy it.
4150                if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0) {
4151                    shouldChangeConfig = true;
4152                }
4153            }
4154        }
4155
4156        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb
4157                + ": shouldChangeConfig=" + shouldChangeConfig);
4158        if (shouldChangeConfig) {
4159            cb.onConfigurationChanged(config);
4160
4161            if (activity != null) {
4162                if (!activity.mCalled) {
4163                    throw new SuperNotCalledException(
4164                            "Activity " + activity.getLocalClassName() +
4165                        " did not call through to super.onConfigurationChanged()");
4166                }
4167                activity.mConfigChangeFlags = 0;
4168                activity.mCurrentConfig = new Configuration(config);
4169            }
4170        }
4171    }
4172
4173    public final void applyConfigurationToResources(Configuration config) {
4174        synchronized (mResourcesManager) {
4175            mResourcesManager.applyConfigurationToResourcesLocked(config, null);
4176        }
4177    }
4178
4179    final Configuration applyCompatConfiguration(int displayDensity) {
4180        Configuration config = mConfiguration;
4181        if (mCompatConfiguration == null) {
4182            mCompatConfiguration = new Configuration();
4183        }
4184        mCompatConfiguration.setTo(mConfiguration);
4185        if (mResourcesManager.applyCompatConfiguration(displayDensity, mCompatConfiguration)) {
4186            config = mCompatConfiguration;
4187        }
4188        return config;
4189    }
4190
4191    final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {
4192
4193        int configDiff = 0;
4194
4195        synchronized (mResourcesManager) {
4196            if (mPendingConfiguration != null) {
4197                if (!mPendingConfiguration.isOtherSeqNewer(config)) {
4198                    config = mPendingConfiguration;
4199                    mCurDefaultDisplayDpi = config.densityDpi;
4200                    updateDefaultDensity();
4201                }
4202                mPendingConfiguration = null;
4203            }
4204
4205            if (config == null) {
4206                return;
4207            }
4208
4209            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: "
4210                    + config);
4211
4212            mResourcesManager.applyConfigurationToResourcesLocked(config, compat);
4213
4214            if (mConfiguration == null) {
4215                mConfiguration = new Configuration();
4216            }
4217            if (!mConfiguration.isOtherSeqNewer(config) && compat == null) {
4218                return;
4219            }
4220
4221            configDiff = mConfiguration.updateFrom(config);
4222            config = applyCompatConfiguration(mCurDefaultDisplayDpi);
4223
4224            final Theme systemTheme = getSystemContext().getTheme();
4225            if ((systemTheme.getChangingConfigurations() & configDiff) != 0) {
4226                systemTheme.rebase();
4227            }
4228        }
4229
4230        ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
4231
4232        freeTextLayoutCachesIfNeeded(configDiff);
4233
4234        if (callbacks != null) {
4235            final int N = callbacks.size();
4236            for (int i=0; i<N; i++) {
4237                performConfigurationChanged(callbacks.get(i), config);
4238            }
4239        }
4240    }
4241
4242    static void freeTextLayoutCachesIfNeeded(int configDiff) {
4243        if (configDiff != 0) {
4244            // Ask text layout engine to free its caches if there is a locale change
4245            boolean hasLocaleConfigChange = ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0);
4246            if (hasLocaleConfigChange) {
4247                Canvas.freeTextLayoutCaches();
4248                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Cleared TextLayout Caches");
4249            }
4250        }
4251    }
4252
4253    final void handleActivityConfigurationChanged(ActivityConfigChangeData data) {
4254        ActivityClientRecord r = mActivities.get(data.activityToken);
4255        if (r == null || r.activity == null) {
4256            return;
4257        }
4258
4259        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
4260                + r.activityInfo.name);
4261
4262        r.tmpConfig.setTo(mCompatConfiguration);
4263        if (data.overrideConfig != null) {
4264            r.overrideConfig = data.overrideConfig;
4265            r.tmpConfig.updateFrom(data.overrideConfig);
4266        }
4267        performConfigurationChanged(r.activity, r.tmpConfig);
4268
4269        freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(mCompatConfiguration));
4270
4271        mSomeActivitiesChanged = true;
4272    }
4273
4274    final void handleProfilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) {
4275        if (start) {
4276            try {
4277                switch (profileType) {
4278                    default:
4279                        mProfiler.setProfiler(profilerInfo);
4280                        mProfiler.startProfiling();
4281                        break;
4282                }
4283            } catch (RuntimeException e) {
4284                Slog.w(TAG, "Profiling failed on path " + profilerInfo.profileFile
4285                        + " -- can the process access this path?");
4286            } finally {
4287                try {
4288                    profilerInfo.profileFd.close();
4289                } catch (IOException e) {
4290                    Slog.w(TAG, "Failure closing profile fd", e);
4291                }
4292            }
4293        } else {
4294            switch (profileType) {
4295                default:
4296                    mProfiler.stopProfiling();
4297                    break;
4298            }
4299        }
4300    }
4301
4302    static final void handleDumpHeap(boolean managed, DumpHeapData dhd) {
4303        if (managed) {
4304            try {
4305                Debug.dumpHprofData(dhd.path, dhd.fd.getFileDescriptor());
4306            } catch (IOException e) {
4307                Slog.w(TAG, "Managed heap dump failed on path " + dhd.path
4308                        + " -- can the process access this path?");
4309            } finally {
4310                try {
4311                    dhd.fd.close();
4312                } catch (IOException e) {
4313                    Slog.w(TAG, "Failure closing profile fd", e);
4314                }
4315            }
4316        } else {
4317            Debug.dumpNativeHeap(dhd.fd.getFileDescriptor());
4318        }
4319        try {
4320            ActivityManagerNative.getDefault().dumpHeapFinished(dhd.path);
4321        } catch (RemoteException e) {
4322        }
4323    }
4324
4325    final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
4326        boolean hasPkgInfo = false;
4327        if (packages != null) {
4328            synchronized (mResourcesManager) {
4329                for (int i=packages.length-1; i>=0; i--) {
4330                    //Slog.i(TAG, "Cleaning old package: " + packages[i]);
4331                    if (!hasPkgInfo) {
4332                        WeakReference<LoadedApk> ref;
4333                        ref = mPackages.get(packages[i]);
4334                        if (ref != null && ref.get() != null) {
4335                            hasPkgInfo = true;
4336                        } else {
4337                            ref = mResourcePackages.get(packages[i]);
4338                            if (ref != null && ref.get() != null) {
4339                                hasPkgInfo = true;
4340                            }
4341                        }
4342                    }
4343                    mPackages.remove(packages[i]);
4344                    mResourcePackages.remove(packages[i]);
4345                }
4346            }
4347        }
4348        ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
4349                hasPkgInfo);
4350    }
4351
4352    final void handleLowMemory() {
4353        ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
4354
4355        final int N = callbacks.size();
4356        for (int i=0; i<N; i++) {
4357            callbacks.get(i).onLowMemory();
4358        }
4359
4360        // Ask SQLite to free up as much memory as it can, mostly from its page caches.
4361        if (Process.myUid() != Process.SYSTEM_UID) {
4362            int sqliteReleased = SQLiteDatabase.releaseMemory();
4363            EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
4364        }
4365
4366        // Ask graphics to free up as much as possible (font/image caches)
4367        Canvas.freeCaches();
4368
4369        // Ask text layout engine to free also as much as possible
4370        Canvas.freeTextLayoutCaches();
4371
4372        BinderInternal.forceGc("mem");
4373    }
4374
4375    final void handleTrimMemory(int level) {
4376        if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level);
4377
4378        ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
4379
4380        final int N = callbacks.size();
4381        for (int i = 0; i < N; i++) {
4382            callbacks.get(i).onTrimMemory(level);
4383        }
4384
4385        WindowManagerGlobal.getInstance().trimMemory(level);
4386    }
4387
4388    private void setupGraphicsSupport(LoadedApk info, File cacheDir) {
4389        if (Process.isIsolated()) {
4390            // Isolated processes aren't going to do UI.
4391            return;
4392        }
4393        try {
4394            int uid = Process.myUid();
4395            String[] packages = getPackageManager().getPackagesForUid(uid);
4396
4397            // If there are several packages in this application we won't
4398            // initialize the graphics disk caches
4399            if (packages != null && packages.length == 1) {
4400                HardwareRenderer.setupDiskCache(cacheDir);
4401                RenderScriptCacheDir.setupDiskCache(cacheDir);
4402            }
4403        } catch (RemoteException e) {
4404            // Ignore
4405        }
4406    }
4407
4408    private void updateDefaultDensity() {
4409        if (mCurDefaultDisplayDpi != Configuration.DENSITY_DPI_UNDEFINED
4410                && mCurDefaultDisplayDpi != DisplayMetrics.DENSITY_DEVICE
4411                && !mDensityCompatMode) {
4412            Slog.i(TAG, "Switching default density from "
4413                    + DisplayMetrics.DENSITY_DEVICE + " to "
4414                    + mCurDefaultDisplayDpi);
4415            DisplayMetrics.DENSITY_DEVICE = mCurDefaultDisplayDpi;
4416            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
4417        }
4418    }
4419
4420    private void handleBindApplication(AppBindData data) {
4421        mBoundApplication = data;
4422        mConfiguration = new Configuration(data.config);
4423        mCompatConfiguration = new Configuration(data.config);
4424
4425        mProfiler = new Profiler();
4426        if (data.initProfilerInfo != null) {
4427            mProfiler.profileFile = data.initProfilerInfo.profileFile;
4428            mProfiler.profileFd = data.initProfilerInfo.profileFd;
4429            mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval;
4430            mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler;
4431        }
4432
4433        // send up app name; do this *before* waiting for debugger
4434        Process.setArgV0(data.processName);
4435        android.ddm.DdmHandleAppName.setAppName(data.processName,
4436                                                UserHandle.myUserId());
4437
4438        if (data.persistent) {
4439            // Persistent processes on low-memory devices do not get to
4440            // use hardware accelerated drawing, since this can add too much
4441            // overhead to the process.
4442            if (!ActivityManager.isHighEndGfx()) {
4443                HardwareRenderer.disable(false);
4444            }
4445        }
4446
4447        if (mProfiler.profileFd != null) {
4448            mProfiler.startProfiling();
4449        }
4450
4451        // If the app is Honeycomb MR1 or earlier, switch its AsyncTask
4452        // implementation to use the pool executor.  Normally, we use the
4453        // serialized executor as the default. This has to happen in the
4454        // main thread so the main looper is set right.
4455        if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
4456            AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
4457        }
4458
4459        Message.updateCheckRecycle(data.appInfo.targetSdkVersion);
4460
4461        /*
4462         * Before spawning a new process, reset the time zone to be the system time zone.
4463         * This needs to be done because the system time zone could have changed after the
4464         * the spawning of this process. Without doing this this process would have the incorrect
4465         * system time zone.
4466         */
4467        TimeZone.setDefault(null);
4468
4469        /*
4470         * Initialize the default locale in this process for the reasons we set the time zone.
4471         */
4472        Locale.setDefault(data.config.locale);
4473
4474        /*
4475         * Update the system configuration since its preloaded and might not
4476         * reflect configuration changes. The configuration object passed
4477         * in AppBindData can be safely assumed to be up to date
4478         */
4479        mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
4480        mCurDefaultDisplayDpi = data.config.densityDpi;
4481        applyCompatConfiguration(mCurDefaultDisplayDpi);
4482
4483        data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
4484
4485        /**
4486         * Switch this process to density compatibility mode if needed.
4487         */
4488        if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
4489                == 0) {
4490            mDensityCompatMode = true;
4491            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
4492        }
4493        updateDefaultDensity();
4494
4495        final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
4496        if (!Process.isIsolated()) {
4497            final File cacheDir = appContext.getCacheDir();
4498
4499            if (cacheDir != null) {
4500                // Provide a usable directory for temporary files
4501                System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
4502            } else {
4503                Log.v(TAG, "Unable to initialize \"java.io.tmpdir\" property due to missing cache directory");
4504            }
4505
4506            // Use codeCacheDir to store generated/compiled graphics code
4507            final File codeCacheDir = appContext.getCodeCacheDir();
4508            if (codeCacheDir != null) {
4509                setupGraphicsSupport(data.info, codeCacheDir);
4510            } else {
4511                Log.e(TAG, "Unable to setupGraphicsSupport due to missing code-cache directory");
4512            }
4513        }
4514
4515
4516        final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));
4517        DateFormat.set24HourTimePref(is24Hr);
4518
4519        View.mDebugViewAttributes =
4520                mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;
4521
4522        /**
4523         * For system applications on userdebug/eng builds, log stack
4524         * traces of disk and network access to dropbox for analysis.
4525         */
4526        if ((data.appInfo.flags &
4527             (ApplicationInfo.FLAG_SYSTEM |
4528              ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) {
4529            StrictMode.conditionallyEnableDebugLogging();
4530        }
4531
4532        /**
4533         * For apps targetting SDK Honeycomb or later, we don't allow
4534         * network usage on the main event loop / UI thread.
4535         *
4536         * Note to those grepping:  this is what ultimately throws
4537         * NetworkOnMainThreadException ...
4538         */
4539        if (data.appInfo.targetSdkVersion > 9) {
4540            StrictMode.enableDeathOnNetwork();
4541        }
4542
4543        NetworkSecurityPolicy.getInstance().setCleartextTrafficPermitted(
4544                (data.appInfo.flags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0);
4545
4546        if (data.debugMode != IApplicationThread.DEBUG_OFF) {
4547            // XXX should have option to change the port.
4548            Debug.changeDebugPort(8100);
4549            if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
4550                Slog.w(TAG, "Application " + data.info.getPackageName()
4551                      + " is waiting for the debugger on port 8100...");
4552
4553                IActivityManager mgr = ActivityManagerNative.getDefault();
4554                try {
4555                    mgr.showWaitingForDebugger(mAppThread, true);
4556                } catch (RemoteException ex) {
4557                }
4558
4559                Debug.waitForDebugger();
4560
4561                try {
4562                    mgr.showWaitingForDebugger(mAppThread, false);
4563                } catch (RemoteException ex) {
4564                }
4565
4566            } else {
4567                Slog.w(TAG, "Application " + data.info.getPackageName()
4568                      + " can be debugged on port 8100...");
4569            }
4570        }
4571
4572        // Enable OpenGL tracing if required
4573        if (data.enableOpenGlTrace) {
4574            GLUtils.setTracingLevel(1);
4575        }
4576
4577        // Allow application-generated systrace messages if we're debuggable.
4578        boolean appTracingAllowed = (data.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0;
4579        Trace.setAppTracingAllowed(appTracingAllowed);
4580
4581        /**
4582         * Initialize the default http proxy in this process for the reasons we set the time zone.
4583         */
4584        IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
4585        if (b != null) {
4586            // In pre-boot mode (doing initial launch to collect password), not
4587            // all system is up.  This includes the connectivity service, so don't
4588            // crash if we can't get it.
4589            IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
4590            try {
4591                final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
4592                Proxy.setHttpProxySystemProperty(proxyInfo);
4593            } catch (RemoteException e) {}
4594        }
4595
4596        if (data.instrumentationName != null) {
4597            InstrumentationInfo ii = null;
4598            try {
4599                ii = appContext.getPackageManager().
4600                    getInstrumentationInfo(data.instrumentationName, 0);
4601            } catch (PackageManager.NameNotFoundException e) {
4602            }
4603            if (ii == null) {
4604                throw new RuntimeException(
4605                    "Unable to find instrumentation info for: "
4606                    + data.instrumentationName);
4607            }
4608
4609            mInstrumentationPackageName = ii.packageName;
4610            mInstrumentationAppDir = ii.sourceDir;
4611            mInstrumentationSplitAppDirs = ii.splitSourceDirs;
4612            mInstrumentationLibDir = ii.nativeLibraryDir;
4613            mInstrumentedAppDir = data.info.getAppDir();
4614            mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
4615            mInstrumentedLibDir = data.info.getLibDir();
4616
4617            ApplicationInfo instrApp = new ApplicationInfo();
4618            instrApp.packageName = ii.packageName;
4619            instrApp.sourceDir = ii.sourceDir;
4620            instrApp.publicSourceDir = ii.publicSourceDir;
4621            instrApp.splitSourceDirs = ii.splitSourceDirs;
4622            instrApp.splitPublicSourceDirs = ii.splitPublicSourceDirs;
4623            instrApp.dataDir = ii.dataDir;
4624            instrApp.nativeLibraryDir = ii.nativeLibraryDir;
4625            LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
4626                    appContext.getClassLoader(), false, true, false);
4627            ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
4628
4629            try {
4630                java.lang.ClassLoader cl = instrContext.getClassLoader();
4631                mInstrumentation = (Instrumentation)
4632                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
4633            } catch (Exception e) {
4634                throw new RuntimeException(
4635                    "Unable to instantiate instrumentation "
4636                    + data.instrumentationName + ": " + e.toString(), e);
4637            }
4638
4639            mInstrumentation.init(this, instrContext, appContext,
4640                   new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher,
4641                   data.instrumentationUiAutomationConnection);
4642
4643            if (mProfiler.profileFile != null && !ii.handleProfiling
4644                    && mProfiler.profileFd == null) {
4645                mProfiler.handlingProfiling = true;
4646                File file = new File(mProfiler.profileFile);
4647                file.getParentFile().mkdirs();
4648                Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
4649            }
4650
4651        } else {
4652            mInstrumentation = new Instrumentation();
4653        }
4654
4655        if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
4656            dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
4657        } else {
4658            // Small heap, clamp to the current growth limit and let the heap release
4659            // pages after the growth limit to the non growth limit capacity. b/18387825
4660            dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
4661        }
4662
4663        // Allow disk access during application and provider setup. This could
4664        // block processing ordered broadcasts, but later processing would
4665        // probably end up doing the same disk access.
4666        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
4667        try {
4668            // If the app is being launched for full backup or restore, bring it up in
4669            // a restricted environment with the base application class.
4670            Application app = data.info.makeApplication(data.restrictedBackupMode, null);
4671            mInitialApplication = app;
4672
4673            // don't bring up providers in restricted mode; they may depend on the
4674            // app's custom Application class
4675            if (!data.restrictedBackupMode) {
4676                List<ProviderInfo> providers = data.providers;
4677                if (providers != null) {
4678                    installContentProviders(app, providers);
4679                    // For process that contains content providers, we want to
4680                    // ensure that the JIT is enabled "at some point".
4681                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
4682                }
4683            }
4684
4685            // Do this after providers, since instrumentation tests generally start their
4686            // test thread at this point, and we don't want that racing.
4687            try {
4688                mInstrumentation.onCreate(data.instrumentationArgs);
4689            }
4690            catch (Exception e) {
4691                throw new RuntimeException(
4692                    "Exception thrown in onCreate() of "
4693                    + data.instrumentationName + ": " + e.toString(), e);
4694            }
4695
4696            try {
4697                mInstrumentation.callApplicationOnCreate(app);
4698            } catch (Exception e) {
4699                if (!mInstrumentation.onException(app, e)) {
4700                    throw new RuntimeException(
4701                        "Unable to create application " + app.getClass().getName()
4702                        + ": " + e.toString(), e);
4703                }
4704            }
4705        } finally {
4706            StrictMode.setThreadPolicy(savedPolicy);
4707        }
4708    }
4709
4710    /*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
4711        IActivityManager am = ActivityManagerNative.getDefault();
4712        if (mProfiler.profileFile != null && mProfiler.handlingProfiling
4713                && mProfiler.profileFd == null) {
4714            Debug.stopMethodTracing();
4715        }
4716        //Slog.i(TAG, "am: " + ActivityManagerNative.getDefault()
4717        //      + ", app thr: " + mAppThread);
4718        try {
4719            am.finishInstrumentation(mAppThread, resultCode, results);
4720        } catch (RemoteException ex) {
4721        }
4722    }
4723
4724    private void installContentProviders(
4725            Context context, List<ProviderInfo> providers) {
4726        final ArrayList<IActivityManager.ContentProviderHolder> results =
4727            new ArrayList<IActivityManager.ContentProviderHolder>();
4728
4729        for (ProviderInfo cpi : providers) {
4730            if (DEBUG_PROVIDER) {
4731                StringBuilder buf = new StringBuilder(128);
4732                buf.append("Pub ");
4733                buf.append(cpi.authority);
4734                buf.append(": ");
4735                buf.append(cpi.name);
4736                Log.i(TAG, buf.toString());
4737            }
4738            IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
4739                    false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
4740            if (cph != null) {
4741                cph.noReleaseNeeded = true;
4742                results.add(cph);
4743            }
4744        }
4745
4746        try {
4747            ActivityManagerNative.getDefault().publishContentProviders(
4748                getApplicationThread(), results);
4749        } catch (RemoteException ex) {
4750        }
4751    }
4752
4753    public final IContentProvider acquireProvider(
4754            Context c, String auth, int userId, boolean stable) {
4755        final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
4756        if (provider != null) {
4757            return provider;
4758        }
4759
4760        // There is a possible race here.  Another thread may try to acquire
4761        // the same provider at the same time.  When this happens, we want to ensure
4762        // that the first one wins.
4763        // Note that we cannot hold the lock while acquiring and installing the
4764        // provider since it might take a long time to run and it could also potentially
4765        // be re-entrant in the case where the provider is in the same process.
4766        IActivityManager.ContentProviderHolder holder = null;
4767        try {
4768            holder = ActivityManagerNative.getDefault().getContentProvider(
4769                    getApplicationThread(), auth, userId, stable);
4770        } catch (RemoteException ex) {
4771        }
4772        if (holder == null) {
4773            Slog.e(TAG, "Failed to find provider info for " + auth);
4774            return null;
4775        }
4776
4777        // Install provider will increment the reference count for us, and break
4778        // any ties in the race.
4779        holder = installProvider(c, holder, holder.info,
4780                true /*noisy*/, holder.noReleaseNeeded, stable);
4781        return holder.provider;
4782    }
4783
4784    private final void incProviderRefLocked(ProviderRefCount prc, boolean stable) {
4785        if (stable) {
4786            prc.stableCount += 1;
4787            if (prc.stableCount == 1) {
4788                // We are acquiring a new stable reference on the provider.
4789                int unstableDelta;
4790                if (prc.removePending) {
4791                    // We have a pending remove operation, which is holding the
4792                    // last unstable reference.  At this point we are converting
4793                    // that unstable reference to our new stable reference.
4794                    unstableDelta = -1;
4795                    // Cancel the removal of the provider.
4796                    if (DEBUG_PROVIDER) {
4797                        Slog.v(TAG, "incProviderRef: stable "
4798                                + "snatched provider from the jaws of death");
4799                    }
4800                    prc.removePending = false;
4801                    // There is a race! It fails to remove the message, which
4802                    // will be handled in completeRemoveProvider().
4803                    mH.removeMessages(H.REMOVE_PROVIDER, prc);
4804                } else {
4805                    unstableDelta = 0;
4806                }
4807                try {
4808                    if (DEBUG_PROVIDER) {
4809                        Slog.v(TAG, "incProviderRef Now stable - "
4810                                + prc.holder.info.name + ": unstableDelta="
4811                                + unstableDelta);
4812                    }
4813                    ActivityManagerNative.getDefault().refContentProvider(
4814                            prc.holder.connection, 1, unstableDelta);
4815                } catch (RemoteException e) {
4816                    //do nothing content provider object is dead any way
4817                }
4818            }
4819        } else {
4820            prc.unstableCount += 1;
4821            if (prc.unstableCount == 1) {
4822                // We are acquiring a new unstable reference on the provider.
4823                if (prc.removePending) {
4824                    // Oh look, we actually have a remove pending for the
4825                    // provider, which is still holding the last unstable
4826                    // reference.  We just need to cancel that to take new
4827                    // ownership of the reference.
4828                    if (DEBUG_PROVIDER) {
4829                        Slog.v(TAG, "incProviderRef: unstable "
4830                                + "snatched provider from the jaws of death");
4831                    }
4832                    prc.removePending = false;
4833                    mH.removeMessages(H.REMOVE_PROVIDER, prc);
4834                } else {
4835                    // First unstable ref, increment our count in the
4836                    // activity manager.
4837                    try {
4838                        if (DEBUG_PROVIDER) {
4839                            Slog.v(TAG, "incProviderRef: Now unstable - "
4840                                    + prc.holder.info.name);
4841                        }
4842                        ActivityManagerNative.getDefault().refContentProvider(
4843                                prc.holder.connection, 0, 1);
4844                    } catch (RemoteException e) {
4845                        //do nothing content provider object is dead any way
4846                    }
4847                }
4848            }
4849        }
4850    }
4851
4852    public final IContentProvider acquireExistingProvider(
4853            Context c, String auth, int userId, boolean stable) {
4854        synchronized (mProviderMap) {
4855            final ProviderKey key = new ProviderKey(auth, userId);
4856            final ProviderClientRecord pr = mProviderMap.get(key);
4857            if (pr == null) {
4858                return null;
4859            }
4860
4861            IContentProvider provider = pr.mProvider;
4862            IBinder jBinder = provider.asBinder();
4863            if (!jBinder.isBinderAlive()) {
4864                // The hosting process of the provider has died; we can't
4865                // use this one.
4866                Log.i(TAG, "Acquiring provider " + auth + " for user " + userId
4867                        + ": existing object's process dead");
4868                handleUnstableProviderDiedLocked(jBinder, true);
4869                return null;
4870            }
4871
4872            // Only increment the ref count if we have one.  If we don't then the
4873            // provider is not reference counted and never needs to be released.
4874            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4875            if (prc != null) {
4876                incProviderRefLocked(prc, stable);
4877            }
4878            return provider;
4879        }
4880    }
4881
4882    public final boolean releaseProvider(IContentProvider provider, boolean stable) {
4883        if (provider == null) {
4884            return false;
4885        }
4886
4887        IBinder jBinder = provider.asBinder();
4888        synchronized (mProviderMap) {
4889            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4890            if (prc == null) {
4891                // The provider has no ref count, no release is needed.
4892                return false;
4893            }
4894
4895            boolean lastRef = false;
4896            if (stable) {
4897                if (prc.stableCount == 0) {
4898                    if (DEBUG_PROVIDER) Slog.v(TAG,
4899                            "releaseProvider: stable ref count already 0, how?");
4900                    return false;
4901                }
4902                prc.stableCount -= 1;
4903                if (prc.stableCount == 0) {
4904                    // What we do at this point depends on whether there are
4905                    // any unstable refs left: if there are, we just tell the
4906                    // activity manager to decrement its stable count; if there
4907                    // aren't, we need to enqueue this provider to be removed,
4908                    // and convert to holding a single unstable ref while
4909                    // doing so.
4910                    lastRef = prc.unstableCount == 0;
4911                    try {
4912                        if (DEBUG_PROVIDER) {
4913                            Slog.v(TAG, "releaseProvider: No longer stable w/lastRef="
4914                                    + lastRef + " - " + prc.holder.info.name);
4915                        }
4916                        ActivityManagerNative.getDefault().refContentProvider(
4917                                prc.holder.connection, -1, lastRef ? 1 : 0);
4918                    } catch (RemoteException e) {
4919                        //do nothing content provider object is dead any way
4920                    }
4921                }
4922            } else {
4923                if (prc.unstableCount == 0) {
4924                    if (DEBUG_PROVIDER) Slog.v(TAG,
4925                            "releaseProvider: unstable ref count already 0, how?");
4926                    return false;
4927                }
4928                prc.unstableCount -= 1;
4929                if (prc.unstableCount == 0) {
4930                    // If this is the last reference, we need to enqueue
4931                    // this provider to be removed instead of telling the
4932                    // activity manager to remove it at this point.
4933                    lastRef = prc.stableCount == 0;
4934                    if (!lastRef) {
4935                        try {
4936                            if (DEBUG_PROVIDER) {
4937                                Slog.v(TAG, "releaseProvider: No longer unstable - "
4938                                        + prc.holder.info.name);
4939                            }
4940                            ActivityManagerNative.getDefault().refContentProvider(
4941                                    prc.holder.connection, 0, -1);
4942                        } catch (RemoteException e) {
4943                            //do nothing content provider object is dead any way
4944                        }
4945                    }
4946                }
4947            }
4948
4949            if (lastRef) {
4950                if (!prc.removePending) {
4951                    // Schedule the actual remove asynchronously, since we don't know the context
4952                    // this will be called in.
4953                    // TODO: it would be nice to post a delayed message, so
4954                    // if we come back and need the same provider quickly
4955                    // we will still have it available.
4956                    if (DEBUG_PROVIDER) {
4957                        Slog.v(TAG, "releaseProvider: Enqueueing pending removal - "
4958                                + prc.holder.info.name);
4959                    }
4960                    prc.removePending = true;
4961                    Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, prc);
4962                    mH.sendMessage(msg);
4963                } else {
4964                    Slog.w(TAG, "Duplicate remove pending of provider " + prc.holder.info.name);
4965                }
4966            }
4967            return true;
4968        }
4969    }
4970
4971    final void completeRemoveProvider(ProviderRefCount prc) {
4972        synchronized (mProviderMap) {
4973            if (!prc.removePending) {
4974                // There was a race!  Some other client managed to acquire
4975                // the provider before the removal was completed.
4976                // Abort the removal.  We will do it later.
4977                if (DEBUG_PROVIDER) Slog.v(TAG, "completeRemoveProvider: lost the race, "
4978                        + "provider still in use");
4979                return;
4980            }
4981
4982            // More complicated race!! Some client managed to acquire the
4983            // provider and release it before the removal was completed.
4984            // Continue the removal, and abort the next remove message.
4985            prc.removePending = false;
4986
4987            final IBinder jBinder = prc.holder.provider.asBinder();
4988            ProviderRefCount existingPrc = mProviderRefCountMap.get(jBinder);
4989            if (existingPrc == prc) {
4990                mProviderRefCountMap.remove(jBinder);
4991            }
4992
4993            for (int i=mProviderMap.size()-1; i>=0; i--) {
4994                ProviderClientRecord pr = mProviderMap.valueAt(i);
4995                IBinder myBinder = pr.mProvider.asBinder();
4996                if (myBinder == jBinder) {
4997                    mProviderMap.removeAt(i);
4998                }
4999            }
5000        }
5001
5002        try {
5003            if (DEBUG_PROVIDER) {
5004                Slog.v(TAG, "removeProvider: Invoking ActivityManagerNative."
5005                        + "removeContentProvider(" + prc.holder.info.name + ")");
5006            }
5007            ActivityManagerNative.getDefault().removeContentProvider(
5008                    prc.holder.connection, false);
5009        } catch (RemoteException e) {
5010            //do nothing content provider object is dead any way
5011        }
5012    }
5013
5014    final void handleUnstableProviderDied(IBinder provider, boolean fromClient) {
5015        synchronized (mProviderMap) {
5016            handleUnstableProviderDiedLocked(provider, fromClient);
5017        }
5018    }
5019
5020    final void handleUnstableProviderDiedLocked(IBinder provider, boolean fromClient) {
5021        ProviderRefCount prc = mProviderRefCountMap.get(provider);
5022        if (prc != null) {
5023            if (DEBUG_PROVIDER) Slog.v(TAG, "Cleaning up dead provider "
5024                    + provider + " " + prc.holder.info.name);
5025            mProviderRefCountMap.remove(provider);
5026            for (int i=mProviderMap.size()-1; i>=0; i--) {
5027                ProviderClientRecord pr = mProviderMap.valueAt(i);
5028                if (pr != null && pr.mProvider.asBinder() == provider) {
5029                    Slog.i(TAG, "Removing dead content provider:" + pr.mProvider.toString());
5030                    mProviderMap.removeAt(i);
5031                }
5032            }
5033
5034            if (fromClient) {
5035                // We found out about this due to execution in our client
5036                // code.  Tell the activity manager about it now, to ensure
5037                // that the next time we go to do anything with the provider
5038                // it knows it is dead (so we don't race with its death
5039                // notification).
5040                try {
5041                    ActivityManagerNative.getDefault().unstableProviderDied(
5042                            prc.holder.connection);
5043                } catch (RemoteException e) {
5044                    //do nothing content provider object is dead any way
5045                }
5046            }
5047        }
5048    }
5049
5050    final void appNotRespondingViaProvider(IBinder provider) {
5051        synchronized (mProviderMap) {
5052            ProviderRefCount prc = mProviderRefCountMap.get(provider);
5053            if (prc != null) {
5054                try {
5055                    ActivityManagerNative.getDefault()
5056                            .appNotRespondingViaProvider(prc.holder.connection);
5057                } catch (RemoteException e) {
5058                }
5059            }
5060        }
5061    }
5062
5063    private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,
5064            ContentProvider localProvider, IActivityManager.ContentProviderHolder holder) {
5065        final String auths[] = holder.info.authority.split(";");
5066        final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid);
5067
5068        final ProviderClientRecord pcr = new ProviderClientRecord(
5069                auths, provider, localProvider, holder);
5070        for (String auth : auths) {
5071            final ProviderKey key = new ProviderKey(auth, userId);
5072            final ProviderClientRecord existing = mProviderMap.get(key);
5073            if (existing != null) {
5074                Slog.w(TAG, "Content provider " + pcr.mHolder.info.name
5075                        + " already published as " + auth);
5076            } else {
5077                mProviderMap.put(key, pcr);
5078            }
5079        }
5080        return pcr;
5081    }
5082
5083    /**
5084     * Installs the provider.
5085     *
5086     * Providers that are local to the process or that come from the system server
5087     * may be installed permanently which is indicated by setting noReleaseNeeded to true.
5088     * Other remote providers are reference counted.  The initial reference count
5089     * for all reference counted providers is one.  Providers that are not reference
5090     * counted do not have a reference count (at all).
5091     *
5092     * This method detects when a provider has already been installed.  When this happens,
5093     * it increments the reference count of the existing provider (if appropriate)
5094     * and returns the existing provider.  This can happen due to concurrent
5095     * attempts to acquire the same provider.
5096     */
5097    private IActivityManager.ContentProviderHolder installProvider(Context context,
5098            IActivityManager.ContentProviderHolder holder, ProviderInfo info,
5099            boolean noisy, boolean noReleaseNeeded, boolean stable) {
5100        ContentProvider localProvider = null;
5101        IContentProvider provider;
5102        if (holder == null || holder.provider == null) {
5103            if (DEBUG_PROVIDER || noisy) {
5104                Slog.d(TAG, "Loading provider " + info.authority + ": "
5105                        + info.name);
5106            }
5107            Context c = null;
5108            ApplicationInfo ai = info.applicationInfo;
5109            if (context.getPackageName().equals(ai.packageName)) {
5110                c = context;
5111            } else if (mInitialApplication != null &&
5112                    mInitialApplication.getPackageName().equals(ai.packageName)) {
5113                c = mInitialApplication;
5114            } else {
5115                try {
5116                    c = context.createPackageContext(ai.packageName,
5117                            Context.CONTEXT_INCLUDE_CODE);
5118                } catch (PackageManager.NameNotFoundException e) {
5119                    // Ignore
5120                }
5121            }
5122            if (c == null) {
5123                Slog.w(TAG, "Unable to get context for package " +
5124                      ai.packageName +
5125                      " while loading content provider " +
5126                      info.name);
5127                return null;
5128            }
5129            try {
5130                final java.lang.ClassLoader cl = c.getClassLoader();
5131                localProvider = (ContentProvider)cl.
5132                    loadClass(info.name).newInstance();
5133                provider = localProvider.getIContentProvider();
5134                if (provider == null) {
5135                    Slog.e(TAG, "Failed to instantiate class " +
5136                          info.name + " from sourceDir " +
5137                          info.applicationInfo.sourceDir);
5138                    return null;
5139                }
5140                if (DEBUG_PROVIDER) Slog.v(
5141                    TAG, "Instantiating local provider " + info.name);
5142                // XXX Need to create the correct context for this provider.
5143                localProvider.attachInfo(c, info);
5144            } catch (java.lang.Exception e) {
5145                if (!mInstrumentation.onException(null, e)) {
5146                    throw new RuntimeException(
5147                            "Unable to get provider " + info.name
5148                            + ": " + e.toString(), e);
5149                }
5150                return null;
5151            }
5152        } else {
5153            provider = holder.provider;
5154            if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": "
5155                    + info.name);
5156        }
5157
5158        IActivityManager.ContentProviderHolder retHolder;
5159
5160        synchronized (mProviderMap) {
5161            if (DEBUG_PROVIDER) Slog.v(TAG, "Checking to add " + provider
5162                    + " / " + info.name);
5163            IBinder jBinder = provider.asBinder();
5164            if (localProvider != null) {
5165                ComponentName cname = new ComponentName(info.packageName, info.name);
5166                ProviderClientRecord pr = mLocalProvidersByName.get(cname);
5167                if (pr != null) {
5168                    if (DEBUG_PROVIDER) {
5169                        Slog.v(TAG, "installProvider: lost the race, "
5170                                + "using existing local provider");
5171                    }
5172                    provider = pr.mProvider;
5173                } else {
5174                    holder = new IActivityManager.ContentProviderHolder(info);
5175                    holder.provider = provider;
5176                    holder.noReleaseNeeded = true;
5177                    pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
5178                    mLocalProviders.put(jBinder, pr);
5179                    mLocalProvidersByName.put(cname, pr);
5180                }
5181                retHolder = pr.mHolder;
5182            } else {
5183                ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
5184                if (prc != null) {
5185                    if (DEBUG_PROVIDER) {
5186                        Slog.v(TAG, "installProvider: lost the race, updating ref count");
5187                    }
5188                    // We need to transfer our new reference to the existing
5189                    // ref count, releasing the old one...  but only if
5190                    // release is needed (that is, it is not running in the
5191                    // system process).
5192                    if (!noReleaseNeeded) {
5193                        incProviderRefLocked(prc, stable);
5194                        try {
5195                            ActivityManagerNative.getDefault().removeContentProvider(
5196                                    holder.connection, stable);
5197                        } catch (RemoteException e) {
5198                            //do nothing content provider object is dead any way
5199                        }
5200                    }
5201                } else {
5202                    ProviderClientRecord client = installProviderAuthoritiesLocked(
5203                            provider, localProvider, holder);
5204                    if (noReleaseNeeded) {
5205                        prc = new ProviderRefCount(holder, client, 1000, 1000);
5206                    } else {
5207                        prc = stable
5208                                ? new ProviderRefCount(holder, client, 1, 0)
5209                                : new ProviderRefCount(holder, client, 0, 1);
5210                    }
5211                    mProviderRefCountMap.put(jBinder, prc);
5212                }
5213                retHolder = prc.holder;
5214            }
5215        }
5216
5217        return retHolder;
5218    }
5219
5220    private void attach(boolean system) {
5221        sCurrentActivityThread = this;
5222        mSystemThread = system;
5223        if (!system) {
5224            ViewRootImpl.addFirstDrawHandler(new Runnable() {
5225                @Override
5226                public void run() {
5227                    ensureJitEnabled();
5228                }
5229            });
5230            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
5231                                                    UserHandle.myUserId());
5232            RuntimeInit.setApplicationObject(mAppThread.asBinder());
5233            final IActivityManager mgr = ActivityManagerNative.getDefault();
5234            try {
5235                mgr.attachApplication(mAppThread);
5236            } catch (RemoteException ex) {
5237                // Ignore
5238            }
5239            // Watch for getting close to heap limit.
5240            BinderInternal.addGcWatcher(new Runnable() {
5241                @Override public void run() {
5242                    if (!mSomeActivitiesChanged) {
5243                        return;
5244                    }
5245                    Runtime runtime = Runtime.getRuntime();
5246                    long dalvikMax = runtime.maxMemory();
5247                    long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
5248                    if (dalvikUsed > ((3*dalvikMax)/4)) {
5249                        if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
5250                                + " total=" + (runtime.totalMemory()/1024)
5251                                + " used=" + (dalvikUsed/1024));
5252                        mSomeActivitiesChanged = false;
5253                        try {
5254                            mgr.releaseSomeActivities(mAppThread);
5255                        } catch (RemoteException e) {
5256                        }
5257                    }
5258                }
5259            });
5260        } else {
5261            // Don't set application object here -- if the system crashes,
5262            // we can't display an alert, we just want to die die die.
5263            android.ddm.DdmHandleAppName.setAppName("system_process",
5264                    UserHandle.myUserId());
5265            try {
5266                mInstrumentation = new Instrumentation();
5267                ContextImpl context = ContextImpl.createAppContext(
5268                        this, getSystemContext().mPackageInfo);
5269                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
5270                mInitialApplication.onCreate();
5271            } catch (Exception e) {
5272                throw new RuntimeException(
5273                        "Unable to instantiate Application():" + e.toString(), e);
5274            }
5275        }
5276
5277        // add dropbox logging to libcore
5278        DropBox.setReporter(new DropBoxReporter());
5279
5280        ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
5281            @Override
5282            public void onConfigurationChanged(Configuration newConfig) {
5283                synchronized (mResourcesManager) {
5284                    // We need to apply this change to the resources
5285                    // immediately, because upon returning the view
5286                    // hierarchy will be informed about it.
5287                    if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
5288                        // This actually changed the resources!  Tell
5289                        // everyone about it.
5290                        if (mPendingConfiguration == null ||
5291                                mPendingConfiguration.isOtherSeqNewer(newConfig)) {
5292                            mPendingConfiguration = newConfig;
5293
5294                            sendMessage(H.CONFIGURATION_CHANGED, newConfig);
5295                        }
5296                    }
5297                }
5298            }
5299            @Override
5300            public void onLowMemory() {
5301            }
5302            @Override
5303            public void onTrimMemory(int level) {
5304            }
5305        });
5306    }
5307
5308    public static ActivityThread systemMain() {
5309        // The system process on low-memory devices do not get to use hardware
5310        // accelerated drawing, since this can add too much overhead to the
5311        // process.
5312        if (!ActivityManager.isHighEndGfx()) {
5313            HardwareRenderer.disable(true);
5314        } else {
5315            HardwareRenderer.enableForegroundTrimming();
5316        }
5317        ActivityThread thread = new ActivityThread();
5318        thread.attach(true);
5319        return thread;
5320    }
5321
5322    public final void installSystemProviders(List<ProviderInfo> providers) {
5323        if (providers != null) {
5324            installContentProviders(mInitialApplication, providers);
5325        }
5326    }
5327
5328    public int getIntCoreSetting(String key, int defaultValue) {
5329        synchronized (mResourcesManager) {
5330            if (mCoreSettings != null) {
5331                return mCoreSettings.getInt(key, defaultValue);
5332            }
5333            return defaultValue;
5334        }
5335    }
5336
5337    private static class EventLoggingReporter implements EventLogger.Reporter {
5338        @Override
5339        public void report (int code, Object... list) {
5340            EventLog.writeEvent(code, list);
5341        }
5342    }
5343
5344    private class DropBoxReporter implements DropBox.Reporter {
5345
5346        private DropBoxManager dropBox;
5347
5348        public DropBoxReporter() {}
5349
5350        @Override
5351        public void addData(String tag, byte[] data, int flags) {
5352            ensureInitialized();
5353            dropBox.addData(tag, data, flags);
5354        }
5355
5356        @Override
5357        public void addText(String tag, String data) {
5358            ensureInitialized();
5359            dropBox.addText(tag, data);
5360        }
5361
5362        private synchronized void ensureInitialized() {
5363            if (dropBox == null) {
5364                dropBox = (DropBoxManager) getSystemContext().getSystemService(Context.DROPBOX_SERVICE);
5365            }
5366        }
5367    }
5368
5369    public static void main(String[] args) {
5370        SamplingProfilerIntegration.start();
5371
5372        // CloseGuard defaults to true and can be quite spammy.  We
5373        // disable it here, but selectively enable it later (via
5374        // StrictMode) on debug builds, but using DropBox, not logs.
5375        CloseGuard.setEnabled(false);
5376
5377        Environment.initForCurrentUser();
5378
5379        // Set the reporter for event logging in libcore
5380        EventLogger.setReporter(new EventLoggingReporter());
5381
5382        AndroidKeyStoreProvider.install();
5383
5384        // Make sure TrustedCertificateStore looks in the right place for CA certificates
5385        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
5386        TrustedCertificateStore.setDefaultUserDirectory(configDir);
5387
5388        Process.setArgV0("<pre-initialized>");
5389
5390        Looper.prepareMainLooper();
5391
5392        ActivityThread thread = new ActivityThread();
5393        thread.attach(false);
5394
5395        if (sMainThreadHandler == null) {
5396            sMainThreadHandler = thread.getHandler();
5397        }
5398
5399        if (false) {
5400            Looper.myLooper().setMessageLogging(new
5401                    LogPrinter(Log.DEBUG, "ActivityThread"));
5402        }
5403
5404        Looper.loop();
5405
5406        throw new RuntimeException("Main thread loop unexpectedly exited");
5407    }
5408}
5409