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