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