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