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