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