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