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