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