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