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