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