ActivityThread.java revision 7981909339d0ccd711efaf2ed531be8b57aeb270
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                r.activity.mFragments.noteStateNotSaved();
2703                if (r.pendingIntents != null) {
2704                    deliverNewIntents(r, r.pendingIntents);
2705                    r.pendingIntents = null;
2706                }
2707                if (r.pendingResults != null) {
2708                    deliverResults(r, r.pendingResults);
2709                    r.pendingResults = null;
2710                }
2711                r.activity.performResume();
2712
2713                EventLog.writeEvent(LOG_ON_RESUME_CALLED,
2714                        UserHandle.myUserId(), r.activity.getComponentName().getClassName());
2715
2716                r.paused = false;
2717                r.stopped = false;
2718                r.state = null;
2719            } catch (Exception e) {
2720                if (!mInstrumentation.onException(r.activity, e)) {
2721                    throw new RuntimeException(
2722                        "Unable to resume activity "
2723                        + r.intent.getComponent().toShortString()
2724                        + ": " + e.toString(), e);
2725                }
2726            }
2727        }
2728        return r;
2729    }
2730
2731    static final void cleanUpPendingRemoveWindows(ActivityClientRecord r) {
2732        if (r.mPendingRemoveWindow != null) {
2733            r.mPendingRemoveWindowManager.removeViewImmediate(r.mPendingRemoveWindow);
2734            IBinder wtoken = r.mPendingRemoveWindow.getWindowToken();
2735            if (wtoken != null) {
2736                WindowManagerGlobal.getInstance().closeAll(wtoken,
2737                        r.activity.getClass().getName(), "Activity");
2738            }
2739        }
2740        r.mPendingRemoveWindow = null;
2741        r.mPendingRemoveWindowManager = null;
2742    }
2743
2744    final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
2745            boolean reallyResume) {
2746        // If we are getting ready to gc after going to the background, well
2747        // we are back active so skip it.
2748        unscheduleGcIdler();
2749
2750        ActivityClientRecord r = performResumeActivity(token, clearHide);
2751
2752        if (r != null) {
2753            final Activity a = r.activity;
2754
2755            if (localLOGV) Slog.v(
2756                TAG, "Resume " + r + " started activity: " +
2757                a.mStartedActivity + ", hideForNow: " + r.hideForNow
2758                + ", finished: " + a.mFinished);
2759
2760            final int forwardBit = isForward ?
2761                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
2762
2763            // If the window hasn't yet been added to the window manager,
2764            // and this guy didn't finish itself or start another activity,
2765            // then go ahead and add the window.
2766            boolean willBeVisible = !a.mStartedActivity;
2767            if (!willBeVisible) {
2768                try {
2769                    willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
2770                            a.getActivityToken());
2771                } catch (RemoteException e) {
2772                }
2773            }
2774            if (r.window == null && !a.mFinished && willBeVisible) {
2775                r.window = r.activity.getWindow();
2776                View decor = r.window.getDecorView();
2777                decor.setVisibility(View.INVISIBLE);
2778                ViewManager wm = a.getWindowManager();
2779                WindowManager.LayoutParams l = r.window.getAttributes();
2780                a.mDecor = decor;
2781                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
2782                l.softInputMode |= forwardBit;
2783                if (a.mVisibleFromClient) {
2784                    a.mWindowAdded = true;
2785                    wm.addView(decor, l);
2786                }
2787
2788            // If the window has already been added, but during resume
2789            // we started another activity, then don't yet make the
2790            // window visible.
2791            } else if (!willBeVisible) {
2792                if (localLOGV) Slog.v(
2793                    TAG, "Launch " + r + " mStartedActivity set");
2794                r.hideForNow = true;
2795            }
2796
2797            // Get rid of anything left hanging around.
2798            cleanUpPendingRemoveWindows(r);
2799
2800            // The window is now visible if it has been added, we are not
2801            // simply finishing, and we are not starting another activity.
2802            if (!r.activity.mFinished && willBeVisible
2803                    && r.activity.mDecor != null && !r.hideForNow) {
2804                if (r.newConfig != null) {
2805                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
2806                            + r.activityInfo.name + " with newConfig " + r.newConfig);
2807                    performConfigurationChanged(r.activity, r.newConfig);
2808                    freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.newConfig));
2809                    r.newConfig = null;
2810                }
2811                if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
2812                        + isForward);
2813                WindowManager.LayoutParams l = r.window.getAttributes();
2814                if ((l.softInputMode
2815                        & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
2816                        != forwardBit) {
2817                    l.softInputMode = (l.softInputMode
2818                            & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
2819                            | forwardBit;
2820                    if (r.activity.mVisibleFromClient) {
2821                        ViewManager wm = a.getWindowManager();
2822                        View decor = r.window.getDecorView();
2823                        wm.updateViewLayout(decor, l);
2824                    }
2825                }
2826                r.activity.mVisibleFromServer = true;
2827                mNumVisibleActivities++;
2828                if (r.activity.mVisibleFromClient) {
2829                    r.activity.makeVisible();
2830                }
2831            }
2832
2833            if (!r.onlyLocalRequest) {
2834                r.nextIdle = mNewActivities;
2835                mNewActivities = r;
2836                if (localLOGV) Slog.v(
2837                    TAG, "Scheduling idle handler for " + r);
2838                Looper.myQueue().addIdleHandler(new Idler());
2839            }
2840            r.onlyLocalRequest = false;
2841
2842            // Tell the activity manager we have resumed.
2843            if (reallyResume) {
2844                try {
2845                    ActivityManagerNative.getDefault().activityResumed(token);
2846                } catch (RemoteException ex) {
2847                }
2848            }
2849
2850        } else {
2851            // If an exception was thrown when trying to resume, then
2852            // just end this activity.
2853            try {
2854                ActivityManagerNative.getDefault()
2855                    .finishActivity(token, Activity.RESULT_CANCELED, null);
2856            } catch (RemoteException ex) {
2857            }
2858        }
2859    }
2860
2861    private int mThumbnailWidth = -1;
2862    private int mThumbnailHeight = -1;
2863    private Bitmap mAvailThumbnailBitmap = null;
2864    private Canvas mThumbnailCanvas = null;
2865
2866    private Bitmap createThumbnailBitmap(ActivityClientRecord r) {
2867        Bitmap thumbnail = mAvailThumbnailBitmap;
2868        try {
2869            if (thumbnail == null) {
2870                int w = mThumbnailWidth;
2871                int h;
2872                if (w < 0) {
2873                    Resources res = r.activity.getResources();
2874                    mThumbnailHeight = h =
2875                        res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
2876
2877                    mThumbnailWidth = w =
2878                        res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
2879                } else {
2880                    h = mThumbnailHeight;
2881                }
2882
2883                // On platforms where we don't want thumbnails, set dims to (0,0)
2884                if ((w > 0) && (h > 0)) {
2885                    thumbnail = Bitmap.createBitmap(r.activity.getResources().getDisplayMetrics(),
2886                            w, h, THUMBNAIL_FORMAT);
2887                    thumbnail.eraseColor(0);
2888                }
2889            }
2890
2891            if (thumbnail != null) {
2892                Canvas cv = mThumbnailCanvas;
2893                if (cv == null) {
2894                    mThumbnailCanvas = cv = new Canvas();
2895                }
2896
2897                cv.setBitmap(thumbnail);
2898                if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
2899                    mAvailThumbnailBitmap = thumbnail;
2900                    thumbnail = null;
2901                }
2902                cv.setBitmap(null);
2903            }
2904
2905        } catch (Exception e) {
2906            if (!mInstrumentation.onException(r.activity, e)) {
2907                throw new RuntimeException(
2908                        "Unable to create thumbnail of "
2909                        + r.intent.getComponent().toShortString()
2910                        + ": " + e.toString(), e);
2911            }
2912            thumbnail = null;
2913        }
2914
2915        return thumbnail;
2916    }
2917
2918    private void handlePauseActivity(IBinder token, boolean finished,
2919            boolean userLeaving, int configChanges) {
2920        ActivityClientRecord r = mActivities.get(token);
2921        if (r != null) {
2922            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
2923            if (userLeaving) {
2924                performUserLeavingActivity(r);
2925            }
2926
2927            r.activity.mConfigChangeFlags |= configChanges;
2928            performPauseActivity(token, finished, r.isPreHoneycomb());
2929
2930            // Make sure any pending writes are now committed.
2931            if (r.isPreHoneycomb()) {
2932                QueuedWork.waitToFinish();
2933            }
2934
2935            // Tell the activity manager we have paused.
2936            try {
2937                ActivityManagerNative.getDefault().activityPaused(token);
2938            } catch (RemoteException ex) {
2939            }
2940        }
2941    }
2942
2943    final void performUserLeavingActivity(ActivityClientRecord r) {
2944        mInstrumentation.callActivityOnUserLeaving(r.activity);
2945    }
2946
2947    final Bundle performPauseActivity(IBinder token, boolean finished,
2948            boolean saveState) {
2949        ActivityClientRecord r = mActivities.get(token);
2950        return r != null ? performPauseActivity(r, finished, saveState) : null;
2951    }
2952
2953    final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
2954            boolean saveState) {
2955        if (r.paused) {
2956            if (r.activity.mFinished) {
2957                // If we are finishing, we won't call onResume() in certain cases.
2958                // So here we likewise don't want to call onPause() if the activity
2959                // isn't resumed.
2960                return null;
2961            }
2962            RuntimeException e = new RuntimeException(
2963                    "Performing pause of activity that is not resumed: "
2964                    + r.intent.getComponent().toShortString());
2965            Slog.e(TAG, e.getMessage(), e);
2966        }
2967        Bundle state = null;
2968        if (finished) {
2969            r.activity.mFinished = true;
2970        }
2971        try {
2972            // Next have the activity save its current state and managed dialogs...
2973            if (!r.activity.mFinished && saveState) {
2974                state = new Bundle();
2975                state.setAllowFds(false);
2976                mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
2977                r.state = state;
2978            }
2979            // Now we are idle.
2980            r.activity.mCalled = false;
2981            mInstrumentation.callActivityOnPause(r.activity);
2982            EventLog.writeEvent(LOG_ON_PAUSE_CALLED, UserHandle.myUserId(),
2983                    r.activity.getComponentName().getClassName());
2984            if (!r.activity.mCalled) {
2985                throw new SuperNotCalledException(
2986                    "Activity " + r.intent.getComponent().toShortString() +
2987                    " did not call through to super.onPause()");
2988            }
2989
2990        } catch (SuperNotCalledException e) {
2991            throw e;
2992
2993        } catch (Exception e) {
2994            if (!mInstrumentation.onException(r.activity, e)) {
2995                throw new RuntimeException(
2996                        "Unable to pause activity "
2997                        + r.intent.getComponent().toShortString()
2998                        + ": " + e.toString(), e);
2999            }
3000        }
3001        r.paused = true;
3002
3003        // Notify any outstanding on paused listeners
3004        ArrayList<OnActivityPausedListener> listeners;
3005        synchronized (mOnPauseListeners) {
3006            listeners = mOnPauseListeners.remove(r.activity);
3007        }
3008        int size = (listeners != null ? listeners.size() : 0);
3009        for (int i = 0; i < size; i++) {
3010            listeners.get(i).onPaused(r.activity);
3011        }
3012
3013        return state;
3014    }
3015
3016    final void performStopActivity(IBinder token, boolean saveState) {
3017        ActivityClientRecord r = mActivities.get(token);
3018        performStopActivityInner(r, null, false, saveState);
3019    }
3020
3021    private static class StopInfo implements Runnable {
3022        ActivityClientRecord activity;
3023        Bundle state;
3024        Bitmap thumbnail;
3025        CharSequence description;
3026
3027        @Override public void run() {
3028            // Tell activity manager we have been stopped.
3029            try {
3030                if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Reporting activity stopped: " + activity);
3031                ActivityManagerNative.getDefault().activityStopped(
3032                    activity.token, state, thumbnail, description);
3033            } catch (RemoteException ex) {
3034            }
3035        }
3036    }
3037
3038    private static final class ProviderRefCount {
3039        public final IActivityManager.ContentProviderHolder holder;
3040        public final ProviderClientRecord client;
3041        public int stableCount;
3042        public int unstableCount;
3043
3044        // When this is set, the stable and unstable ref counts are 0 and
3045        // we have a pending operation scheduled to remove the ref count
3046        // from the activity manager.  On the activity manager we are still
3047        // holding an unstable ref, though it is not reflected in the counts
3048        // here.
3049        public boolean removePending;
3050
3051        ProviderRefCount(IActivityManager.ContentProviderHolder inHolder,
3052                ProviderClientRecord inClient, int sCount, int uCount) {
3053            holder = inHolder;
3054            client = inClient;
3055            stableCount = sCount;
3056            unstableCount = uCount;
3057        }
3058    }
3059
3060    /**
3061     * Core implementation of stopping an activity.  Note this is a little
3062     * tricky because the server's meaning of stop is slightly different
3063     * than our client -- for the server, stop means to save state and give
3064     * it the result when it is done, but the window may still be visible.
3065     * For the client, we want to call onStop()/onStart() to indicate when
3066     * the activity's UI visibillity changes.
3067     */
3068    private void performStopActivityInner(ActivityClientRecord r,
3069            StopInfo info, boolean keepShown, boolean saveState) {
3070        if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
3071        Bundle state = null;
3072        if (r != null) {
3073            if (!keepShown && r.stopped) {
3074                if (r.activity.mFinished) {
3075                    // If we are finishing, we won't call onResume() in certain
3076                    // cases.  So here we likewise don't want to call onStop()
3077                    // if the activity isn't resumed.
3078                    return;
3079                }
3080                RuntimeException e = new RuntimeException(
3081                        "Performing stop of activity that is not resumed: "
3082                        + r.intent.getComponent().toShortString());
3083                Slog.e(TAG, e.getMessage(), e);
3084            }
3085
3086            if (info != null) {
3087                try {
3088                    // First create a thumbnail for the activity...
3089                    // For now, don't create the thumbnail here; we are
3090                    // doing that by doing a screen snapshot.
3091                    info.thumbnail = null; //createThumbnailBitmap(r);
3092                    info.description = r.activity.onCreateDescription();
3093                } catch (Exception e) {
3094                    if (!mInstrumentation.onException(r.activity, e)) {
3095                        throw new RuntimeException(
3096                                "Unable to save state of activity "
3097                                + r.intent.getComponent().toShortString()
3098                                + ": " + e.toString(), e);
3099                    }
3100                }
3101            }
3102
3103            // Next have the activity save its current state and managed dialogs...
3104            if (!r.activity.mFinished && saveState) {
3105                if (r.state == null) {
3106                    state = new Bundle();
3107                    state.setAllowFds(false);
3108                    mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
3109                    r.state = state;
3110                } else {
3111                    state = r.state;
3112                }
3113            }
3114
3115            if (!keepShown) {
3116                try {
3117                    // Now we are idle.
3118                    r.activity.performStop();
3119                } catch (Exception e) {
3120                    if (!mInstrumentation.onException(r.activity, e)) {
3121                        throw new RuntimeException(
3122                                "Unable to stop activity "
3123                                + r.intent.getComponent().toShortString()
3124                                + ": " + e.toString(), e);
3125                    }
3126                }
3127                r.stopped = true;
3128            }
3129
3130            r.paused = true;
3131        }
3132    }
3133
3134    private void updateVisibility(ActivityClientRecord r, boolean show) {
3135        View v = r.activity.mDecor;
3136        if (v != null) {
3137            if (show) {
3138                if (!r.activity.mVisibleFromServer) {
3139                    r.activity.mVisibleFromServer = true;
3140                    mNumVisibleActivities++;
3141                    if (r.activity.mVisibleFromClient) {
3142                        r.activity.makeVisible();
3143                    }
3144                }
3145                if (r.newConfig != null) {
3146                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
3147                            + r.activityInfo.name + " with new config " + r.newConfig);
3148                    performConfigurationChanged(r.activity, r.newConfig);
3149                    freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.newConfig));
3150                    r.newConfig = null;
3151                }
3152            } else {
3153                if (r.activity.mVisibleFromServer) {
3154                    r.activity.mVisibleFromServer = false;
3155                    mNumVisibleActivities--;
3156                    v.setVisibility(View.INVISIBLE);
3157                }
3158            }
3159        }
3160    }
3161
3162    private void handleStopActivity(IBinder token, boolean show, int configChanges) {
3163        ActivityClientRecord r = mActivities.get(token);
3164        r.activity.mConfigChangeFlags |= configChanges;
3165
3166        StopInfo info = new StopInfo();
3167        performStopActivityInner(r, info, show, true);
3168
3169        if (localLOGV) Slog.v(
3170            TAG, "Finishing stop of " + r + ": show=" + show
3171            + " win=" + r.window);
3172
3173        updateVisibility(r, show);
3174
3175        // Make sure any pending writes are now committed.
3176        if (!r.isPreHoneycomb()) {
3177            QueuedWork.waitToFinish();
3178        }
3179
3180        // Schedule the call to tell the activity manager we have
3181        // stopped.  We don't do this immediately, because we want to
3182        // have a chance for any other pending work (in particular memory
3183        // trim requests) to complete before you tell the activity
3184        // manager to proceed and allow us to go fully into the background.
3185        info.activity = r;
3186        info.state = r.state;
3187        mH.post(info);
3188    }
3189
3190    final void performRestartActivity(IBinder token) {
3191        ActivityClientRecord r = mActivities.get(token);
3192        if (r.stopped) {
3193            r.activity.performRestart();
3194            r.stopped = false;
3195        }
3196    }
3197
3198    private void handleWindowVisibility(IBinder token, boolean show) {
3199        ActivityClientRecord r = mActivities.get(token);
3200
3201        if (r == null) {
3202            Log.w(TAG, "handleWindowVisibility: no activity for token " + token);
3203            return;
3204        }
3205
3206        if (!show && !r.stopped) {
3207            performStopActivityInner(r, null, show, false);
3208        } else if (show && r.stopped) {
3209            // If we are getting ready to gc after going to the background, well
3210            // we are back active so skip it.
3211            unscheduleGcIdler();
3212
3213            r.activity.performRestart();
3214            r.stopped = false;
3215        }
3216        if (r.activity.mDecor != null) {
3217            if (false) Slog.v(
3218                TAG, "Handle window " + r + " visibility: " + show);
3219            updateVisibility(r, show);
3220        }
3221    }
3222
3223    private void handleSleeping(IBinder token, boolean sleeping) {
3224        ActivityClientRecord r = mActivities.get(token);
3225
3226        if (r == null) {
3227            Log.w(TAG, "handleSleeping: no activity for token " + token);
3228            return;
3229        }
3230
3231        if (sleeping) {
3232            if (!r.stopped && !r.isPreHoneycomb()) {
3233                try {
3234                    // Now we are idle.
3235                    r.activity.performStop();
3236                } catch (Exception e) {
3237                    if (!mInstrumentation.onException(r.activity, e)) {
3238                        throw new RuntimeException(
3239                                "Unable to stop activity "
3240                                + r.intent.getComponent().toShortString()
3241                                + ": " + e.toString(), e);
3242                    }
3243                }
3244                r.stopped = true;
3245            }
3246
3247            // Make sure any pending writes are now committed.
3248            if (!r.isPreHoneycomb()) {
3249                QueuedWork.waitToFinish();
3250            }
3251
3252            // Tell activity manager we slept.
3253            try {
3254                ActivityManagerNative.getDefault().activitySlept(r.token);
3255            } catch (RemoteException ex) {
3256            }
3257        } else {
3258            if (r.stopped && r.activity.mVisibleFromServer) {
3259                r.activity.performRestart();
3260                r.stopped = false;
3261            }
3262        }
3263    }
3264
3265    private void handleSetCoreSettings(Bundle coreSettings) {
3266        synchronized (mPackages) {
3267            mCoreSettings = coreSettings;
3268        }
3269    }
3270
3271    private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) {
3272        LoadedApk apk = peekPackageInfo(data.pkg, false);
3273        if (apk != null) {
3274            apk.mCompatibilityInfo.set(data.info);
3275        }
3276        apk = peekPackageInfo(data.pkg, true);
3277        if (apk != null) {
3278            apk.mCompatibilityInfo.set(data.info);
3279        }
3280        handleConfigurationChanged(mConfiguration, data.info);
3281        WindowManagerGlobal.getInstance().reportNewConfiguration(mConfiguration);
3282    }
3283
3284    private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
3285        final int N = results.size();
3286        for (int i=0; i<N; i++) {
3287            ResultInfo ri = results.get(i);
3288            try {
3289                if (ri.mData != null) {
3290                    ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
3291                }
3292                if (DEBUG_RESULTS) Slog.v(TAG,
3293                        "Delivering result to activity " + r + " : " + ri);
3294                r.activity.dispatchActivityResult(ri.mResultWho,
3295                        ri.mRequestCode, ri.mResultCode, ri.mData);
3296            } catch (Exception e) {
3297                if (!mInstrumentation.onException(r.activity, e)) {
3298                    throw new RuntimeException(
3299                            "Failure delivering result " + ri + " to activity "
3300                            + r.intent.getComponent().toShortString()
3301                            + ": " + e.toString(), e);
3302                }
3303            }
3304        }
3305    }
3306
3307    private void handleSendResult(ResultData res) {
3308        ActivityClientRecord r = mActivities.get(res.token);
3309        if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
3310        if (r != null) {
3311            final boolean resumed = !r.paused;
3312            if (!r.activity.mFinished && r.activity.mDecor != null
3313                    && r.hideForNow && resumed) {
3314                // We had hidden the activity because it started another
3315                // one...  we have gotten a result back and we are not
3316                // paused, so make sure our window is visible.
3317                updateVisibility(r, true);
3318            }
3319            if (resumed) {
3320                try {
3321                    // Now we are idle.
3322                    r.activity.mCalled = false;
3323                    r.activity.mTemporaryPause = true;
3324                    mInstrumentation.callActivityOnPause(r.activity);
3325                    if (!r.activity.mCalled) {
3326                        throw new SuperNotCalledException(
3327                            "Activity " + r.intent.getComponent().toShortString()
3328                            + " did not call through to super.onPause()");
3329                    }
3330                } catch (SuperNotCalledException e) {
3331                    throw e;
3332                } catch (Exception e) {
3333                    if (!mInstrumentation.onException(r.activity, e)) {
3334                        throw new RuntimeException(
3335                                "Unable to pause activity "
3336                                + r.intent.getComponent().toShortString()
3337                                + ": " + e.toString(), e);
3338                    }
3339                }
3340            }
3341            deliverResults(r, res.results);
3342            if (resumed) {
3343                r.activity.performResume();
3344                r.activity.mTemporaryPause = false;
3345            }
3346        }
3347    }
3348
3349    public final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing) {
3350        return performDestroyActivity(token, finishing, 0, false);
3351    }
3352
3353    private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
3354            int configChanges, boolean getNonConfigInstance) {
3355        ActivityClientRecord r = mActivities.get(token);
3356        Class activityClass = null;
3357        if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
3358        if (r != null) {
3359            activityClass = r.activity.getClass();
3360            r.activity.mConfigChangeFlags |= configChanges;
3361            if (finishing) {
3362                r.activity.mFinished = true;
3363            }
3364            if (!r.paused) {
3365                try {
3366                    r.activity.mCalled = false;
3367                    mInstrumentation.callActivityOnPause(r.activity);
3368                    EventLog.writeEvent(LOG_ON_PAUSE_CALLED, UserHandle.myUserId(),
3369                            r.activity.getComponentName().getClassName());
3370                    if (!r.activity.mCalled) {
3371                        throw new SuperNotCalledException(
3372                            "Activity " + safeToComponentShortString(r.intent)
3373                            + " did not call through to super.onPause()");
3374                    }
3375                } catch (SuperNotCalledException e) {
3376                    throw e;
3377                } catch (Exception e) {
3378                    if (!mInstrumentation.onException(r.activity, e)) {
3379                        throw new RuntimeException(
3380                                "Unable to pause activity "
3381                                + safeToComponentShortString(r.intent)
3382                                + ": " + e.toString(), e);
3383                    }
3384                }
3385                r.paused = true;
3386            }
3387            if (!r.stopped) {
3388                try {
3389                    r.activity.performStop();
3390                } catch (SuperNotCalledException e) {
3391                    throw e;
3392                } catch (Exception e) {
3393                    if (!mInstrumentation.onException(r.activity, e)) {
3394                        throw new RuntimeException(
3395                                "Unable to stop activity "
3396                                + safeToComponentShortString(r.intent)
3397                                + ": " + e.toString(), e);
3398                    }
3399                }
3400                r.stopped = true;
3401            }
3402            if (getNonConfigInstance) {
3403                try {
3404                    r.lastNonConfigurationInstances
3405                            = r.activity.retainNonConfigurationInstances();
3406                } catch (Exception e) {
3407                    if (!mInstrumentation.onException(r.activity, e)) {
3408                        throw new RuntimeException(
3409                                "Unable to retain activity "
3410                                + r.intent.getComponent().toShortString()
3411                                + ": " + e.toString(), e);
3412                    }
3413                }
3414            }
3415            try {
3416                r.activity.mCalled = false;
3417                mInstrumentation.callActivityOnDestroy(r.activity);
3418                if (!r.activity.mCalled) {
3419                    throw new SuperNotCalledException(
3420                        "Activity " + safeToComponentShortString(r.intent) +
3421                        " did not call through to super.onDestroy()");
3422                }
3423                if (r.window != null) {
3424                    r.window.closeAllPanels();
3425                }
3426            } catch (SuperNotCalledException e) {
3427                throw e;
3428            } catch (Exception e) {
3429                if (!mInstrumentation.onException(r.activity, e)) {
3430                    throw new RuntimeException(
3431                            "Unable to destroy activity " + safeToComponentShortString(r.intent)
3432                            + ": " + e.toString(), e);
3433                }
3434            }
3435        }
3436        mActivities.remove(token);
3437        StrictMode.decrementExpectedActivityCount(activityClass);
3438        return r;
3439    }
3440
3441    private static String safeToComponentShortString(Intent intent) {
3442        ComponentName component = intent.getComponent();
3443        return component == null ? "[Unknown]" : component.toShortString();
3444    }
3445
3446    private void handleDestroyActivity(IBinder token, boolean finishing,
3447            int configChanges, boolean getNonConfigInstance) {
3448        ActivityClientRecord r = performDestroyActivity(token, finishing,
3449                configChanges, getNonConfigInstance);
3450        if (r != null) {
3451            cleanUpPendingRemoveWindows(r);
3452            WindowManager wm = r.activity.getWindowManager();
3453            View v = r.activity.mDecor;
3454            if (v != null) {
3455                if (r.activity.mVisibleFromServer) {
3456                    mNumVisibleActivities--;
3457                }
3458                IBinder wtoken = v.getWindowToken();
3459                if (r.activity.mWindowAdded) {
3460                    if (r.onlyLocalRequest) {
3461                        // Hold off on removing this until the new activity's
3462                        // window is being added.
3463                        r.mPendingRemoveWindow = v;
3464                        r.mPendingRemoveWindowManager = wm;
3465                    } else {
3466                        wm.removeViewImmediate(v);
3467                    }
3468                }
3469                if (wtoken != null && r.mPendingRemoveWindow == null) {
3470                    WindowManagerGlobal.getInstance().closeAll(wtoken,
3471                            r.activity.getClass().getName(), "Activity");
3472                }
3473                r.activity.mDecor = null;
3474            }
3475            if (r.mPendingRemoveWindow == null) {
3476                // If we are delaying the removal of the activity window, then
3477                // we can't clean up all windows here.  Note that we can't do
3478                // so later either, which means any windows that aren't closed
3479                // by the app will leak.  Well we try to warning them a lot
3480                // about leaking windows, because that is a bug, so if they are
3481                // using this recreate facility then they get to live with leaks.
3482                WindowManagerGlobal.getInstance().closeAll(token,
3483                        r.activity.getClass().getName(), "Activity");
3484            }
3485
3486            // Mocked out contexts won't be participating in the normal
3487            // process lifecycle, but if we're running with a proper
3488            // ApplicationContext we need to have it tear down things
3489            // cleanly.
3490            Context c = r.activity.getBaseContext();
3491            if (c instanceof ContextImpl) {
3492                ((ContextImpl) c).scheduleFinalCleanup(
3493                        r.activity.getClass().getName(), "Activity");
3494            }
3495        }
3496        if (finishing) {
3497            try {
3498                ActivityManagerNative.getDefault().activityDestroyed(token);
3499            } catch (RemoteException ex) {
3500                // If the system process has died, it's game over for everyone.
3501            }
3502        }
3503    }
3504
3505    public final void requestRelaunchActivity(IBinder token,
3506            List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
3507            int configChanges, boolean notResumed, Configuration config,
3508            boolean fromServer) {
3509        ActivityClientRecord target = null;
3510
3511        synchronized (mPackages) {
3512            for (int i=0; i<mRelaunchingActivities.size(); i++) {
3513                ActivityClientRecord r = mRelaunchingActivities.get(i);
3514                if (r.token == token) {
3515                    target = r;
3516                    if (pendingResults != null) {
3517                        if (r.pendingResults != null) {
3518                            r.pendingResults.addAll(pendingResults);
3519                        } else {
3520                            r.pendingResults = pendingResults;
3521                        }
3522                    }
3523                    if (pendingNewIntents != null) {
3524                        if (r.pendingIntents != null) {
3525                            r.pendingIntents.addAll(pendingNewIntents);
3526                        } else {
3527                            r.pendingIntents = pendingNewIntents;
3528                        }
3529                    }
3530                    break;
3531                }
3532            }
3533
3534            if (target == null) {
3535                target = new ActivityClientRecord();
3536                target.token = token;
3537                target.pendingResults = pendingResults;
3538                target.pendingIntents = pendingNewIntents;
3539                if (!fromServer) {
3540                    ActivityClientRecord existing = mActivities.get(token);
3541                    if (existing != null) {
3542                        target.startsNotResumed = existing.paused;
3543                    }
3544                    target.onlyLocalRequest = true;
3545                }
3546                mRelaunchingActivities.add(target);
3547                queueOrSendMessage(H.RELAUNCH_ACTIVITY, target);
3548            }
3549
3550            if (fromServer) {
3551                target.startsNotResumed = notResumed;
3552                target.onlyLocalRequest = false;
3553            }
3554            if (config != null) {
3555                target.createdConfig = config;
3556            }
3557            target.pendingConfigChanges |= configChanges;
3558        }
3559    }
3560
3561    private void handleRelaunchActivity(ActivityClientRecord tmp) {
3562        // If we are getting ready to gc after going to the background, well
3563        // we are back active so skip it.
3564        unscheduleGcIdler();
3565
3566        Configuration changedConfig = null;
3567        int configChanges = 0;
3568
3569        // First: make sure we have the most recent configuration and most
3570        // recent version of the activity, or skip it if some previous call
3571        // had taken a more recent version.
3572        synchronized (mPackages) {
3573            int N = mRelaunchingActivities.size();
3574            IBinder token = tmp.token;
3575            tmp = null;
3576            for (int i=0; i<N; i++) {
3577                ActivityClientRecord r = mRelaunchingActivities.get(i);
3578                if (r.token == token) {
3579                    tmp = r;
3580                    configChanges |= tmp.pendingConfigChanges;
3581                    mRelaunchingActivities.remove(i);
3582                    i--;
3583                    N--;
3584                }
3585            }
3586
3587            if (tmp == null) {
3588                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Abort, activity not relaunching!");
3589                return;
3590            }
3591
3592            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
3593                    + tmp.token + " with configChanges=0x"
3594                    + Integer.toHexString(configChanges));
3595
3596            if (mPendingConfiguration != null) {
3597                changedConfig = mPendingConfiguration;
3598                mPendingConfiguration = null;
3599            }
3600        }
3601
3602        if (tmp.createdConfig != null) {
3603            // If the activity manager is passing us its current config,
3604            // assume that is really what we want regardless of what we
3605            // may have pending.
3606            if (mConfiguration == null
3607                    || (tmp.createdConfig.isOtherSeqNewer(mConfiguration)
3608                            && mConfiguration.diff(tmp.createdConfig) != 0)) {
3609                if (changedConfig == null
3610                        || tmp.createdConfig.isOtherSeqNewer(changedConfig)) {
3611                    changedConfig = tmp.createdConfig;
3612                }
3613            }
3614        }
3615
3616        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
3617                + tmp.token + ": changedConfig=" + changedConfig);
3618
3619        // If there was a pending configuration change, execute it first.
3620        if (changedConfig != null) {
3621            mCurDefaultDisplayDpi = changedConfig.densityDpi;
3622            updateDefaultDensity();
3623            handleConfigurationChanged(changedConfig, null);
3624        }
3625
3626        ActivityClientRecord r = mActivities.get(tmp.token);
3627        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r);
3628        if (r == null) {
3629            return;
3630        }
3631
3632        r.activity.mConfigChangeFlags |= configChanges;
3633        r.onlyLocalRequest = tmp.onlyLocalRequest;
3634        Intent currentIntent = r.activity.mIntent;
3635
3636        r.activity.mChangingConfigurations = true;
3637
3638        // Need to ensure state is saved.
3639        if (!r.paused) {
3640            performPauseActivity(r.token, false, r.isPreHoneycomb());
3641        }
3642        if (r.state == null && !r.stopped && !r.isPreHoneycomb()) {
3643            r.state = new Bundle();
3644            r.state.setAllowFds(false);
3645            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
3646        }
3647
3648        handleDestroyActivity(r.token, false, configChanges, true);
3649
3650        r.activity = null;
3651        r.window = null;
3652        r.hideForNow = false;
3653        r.nextIdle = null;
3654        // Merge any pending results and pending intents; don't just replace them
3655        if (tmp.pendingResults != null) {
3656            if (r.pendingResults == null) {
3657                r.pendingResults = tmp.pendingResults;
3658            } else {
3659                r.pendingResults.addAll(tmp.pendingResults);
3660            }
3661        }
3662        if (tmp.pendingIntents != null) {
3663            if (r.pendingIntents == null) {
3664                r.pendingIntents = tmp.pendingIntents;
3665            } else {
3666                r.pendingIntents.addAll(tmp.pendingIntents);
3667            }
3668        }
3669        r.startsNotResumed = tmp.startsNotResumed;
3670
3671        handleLaunchActivity(r, currentIntent);
3672    }
3673
3674    private void handleRequestThumbnail(IBinder token) {
3675        ActivityClientRecord r = mActivities.get(token);
3676        Bitmap thumbnail = createThumbnailBitmap(r);
3677        CharSequence description = null;
3678        try {
3679            description = r.activity.onCreateDescription();
3680        } catch (Exception e) {
3681            if (!mInstrumentation.onException(r.activity, e)) {
3682                throw new RuntimeException(
3683                        "Unable to create description of activity "
3684                        + r.intent.getComponent().toShortString()
3685                        + ": " + e.toString(), e);
3686            }
3687        }
3688        //System.out.println("Reporting top thumbnail " + thumbnail);
3689        try {
3690            ActivityManagerNative.getDefault().reportThumbnail(
3691                token, thumbnail, description);
3692        } catch (RemoteException ex) {
3693        }
3694    }
3695
3696    ArrayList<ComponentCallbacks2> collectComponentCallbacks(
3697            boolean allActivities, Configuration newConfig) {
3698        ArrayList<ComponentCallbacks2> callbacks
3699                = new ArrayList<ComponentCallbacks2>();
3700
3701        synchronized (mPackages) {
3702            final int N = mAllApplications.size();
3703            for (int i=0; i<N; i++) {
3704                callbacks.add(mAllApplications.get(i));
3705            }
3706            if (mActivities.size() > 0) {
3707                for (ActivityClientRecord ar : mActivities.values()) {
3708                    Activity a = ar.activity;
3709                    if (a != null) {
3710                        Configuration thisConfig = applyConfigCompatMainThread(mCurDefaultDisplayDpi,
3711                                newConfig, ar.packageInfo.mCompatibilityInfo.getIfNeeded());
3712                        if (!ar.activity.mFinished && (allActivities || !ar.paused)) {
3713                            // If the activity is currently resumed, its configuration
3714                            // needs to change right now.
3715                            callbacks.add(a);
3716                        } else if (thisConfig != null) {
3717                            // Otherwise, we will tell it about the change
3718                            // the next time it is resumed or shown.  Note that
3719                            // the activity manager may, before then, decide the
3720                            // activity needs to be destroyed to handle its new
3721                            // configuration.
3722                            if (DEBUG_CONFIGURATION) {
3723                                Slog.v(TAG, "Setting activity "
3724                                        + ar.activityInfo.name + " newConfig=" + thisConfig);
3725                            }
3726                            ar.newConfig = thisConfig;
3727                        }
3728                    }
3729                }
3730            }
3731            if (mServices.size() > 0) {
3732                for (Service service : mServices.values()) {
3733                    callbacks.add(service);
3734                }
3735            }
3736        }
3737        synchronized (mProviderMap) {
3738            if (mLocalProviders.size() > 0) {
3739                for (ProviderClientRecord providerClientRecord : mLocalProviders.values()) {
3740                    callbacks.add(providerClientRecord.mLocalProvider);
3741                }
3742            }
3743        }
3744
3745        return callbacks;
3746    }
3747
3748    private static void performConfigurationChanged(ComponentCallbacks2 cb, Configuration config) {
3749        // Only for Activity objects, check that they actually call up to their
3750        // superclass implementation.  ComponentCallbacks2 is an interface, so
3751        // we check the runtime type and act accordingly.
3752        Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
3753        if (activity != null) {
3754            activity.mCalled = false;
3755        }
3756
3757        boolean shouldChangeConfig = false;
3758        if ((activity == null) || (activity.mCurrentConfig == null)) {
3759            shouldChangeConfig = true;
3760        } else {
3761
3762            // If the new config is the same as the config this Activity
3763            // is already running with then don't bother calling
3764            // onConfigurationChanged
3765            int diff = activity.mCurrentConfig.diff(config);
3766            if (diff != 0) {
3767                // If this activity doesn't handle any of the config changes
3768                // then don't bother calling onConfigurationChanged as we're
3769                // going to destroy it.
3770                if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0) {
3771                    shouldChangeConfig = true;
3772                }
3773            }
3774        }
3775
3776        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb
3777                + ": shouldChangeConfig=" + shouldChangeConfig);
3778        if (shouldChangeConfig) {
3779            cb.onConfigurationChanged(config);
3780
3781            if (activity != null) {
3782                if (!activity.mCalled) {
3783                    throw new SuperNotCalledException(
3784                            "Activity " + activity.getLocalClassName() +
3785                        " did not call through to super.onConfigurationChanged()");
3786                }
3787                activity.mConfigChangeFlags = 0;
3788                activity.mCurrentConfig = new Configuration(config);
3789            }
3790        }
3791    }
3792
3793    public final void applyConfigurationToResources(Configuration config) {
3794        synchronized (mPackages) {
3795            applyConfigurationToResourcesLocked(config, null);
3796        }
3797    }
3798
3799    final boolean applyConfigurationToResourcesLocked(Configuration config,
3800            CompatibilityInfo compat) {
3801        if (mResConfiguration == null) {
3802            mResConfiguration = new Configuration();
3803        }
3804        if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) {
3805            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
3806                    + mResConfiguration.seq + ", newSeq=" + config.seq);
3807            return false;
3808        }
3809        int changes = mResConfiguration.updateFrom(config);
3810        flushDisplayMetricsLocked();
3811        DisplayMetrics defaultDisplayMetrics = getDisplayMetricsLocked(
3812                Display.DEFAULT_DISPLAY, null);
3813
3814        if (compat != null && (mResCompatibilityInfo == null ||
3815                !mResCompatibilityInfo.equals(compat))) {
3816            mResCompatibilityInfo = compat;
3817            changes |= ActivityInfo.CONFIG_SCREEN_LAYOUT
3818                    | ActivityInfo.CONFIG_SCREEN_SIZE
3819                    | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
3820        }
3821
3822        // set it for java, this also affects newly created Resources
3823        if (config.locale != null) {
3824            Locale.setDefault(config.locale);
3825        }
3826
3827        Resources.updateSystemConfiguration(config, defaultDisplayMetrics, compat);
3828
3829        ApplicationPackageManager.configurationChanged();
3830        //Slog.i(TAG, "Configuration changed in " + currentPackageName());
3831
3832        Configuration tmpConfig = null;
3833
3834        Iterator<Map.Entry<ResourcesKey, WeakReference<Resources>>> it =
3835                mActiveResources.entrySet().iterator();
3836        while (it.hasNext()) {
3837            Map.Entry<ResourcesKey, WeakReference<Resources>> entry = it.next();
3838            Resources r = entry.getValue().get();
3839            if (r != null) {
3840                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
3841                        + r + " config to: " + config);
3842                int displayId = entry.getKey().mDisplayId;
3843                boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
3844                DisplayMetrics dm = defaultDisplayMetrics;
3845                Configuration overrideConfig = entry.getKey().mOverrideConfiguration;
3846                if (!isDefaultDisplay || overrideConfig != null) {
3847                    if (tmpConfig == null) {
3848                        tmpConfig = new Configuration();
3849                    }
3850                    tmpConfig.setTo(config);
3851                    if (!isDefaultDisplay) {
3852                        dm = getDisplayMetricsLocked(displayId, null);
3853                        applyNonDefaultDisplayMetricsToConfigurationLocked(dm, tmpConfig);
3854                    }
3855                    if (overrideConfig != null) {
3856                        tmpConfig.updateFrom(overrideConfig);
3857                    }
3858                    r.updateConfiguration(tmpConfig, dm, compat);
3859                } else {
3860                    r.updateConfiguration(config, dm, compat);
3861                }
3862                //Slog.i(TAG, "Updated app resources " + v.getKey()
3863                //        + " " + r + ": " + r.getConfiguration());
3864            } else {
3865                //Slog.i(TAG, "Removing old resources " + v.getKey());
3866                it.remove();
3867            }
3868        }
3869
3870        return changes != 0;
3871    }
3872
3873    final void applyNonDefaultDisplayMetricsToConfigurationLocked(
3874            DisplayMetrics dm, Configuration config) {
3875        config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
3876        config.densityDpi = dm.densityDpi;
3877        config.screenWidthDp = (int)(dm.widthPixels / dm.density);
3878        config.screenHeightDp = (int)(dm.heightPixels / dm.density);
3879        int sl = Configuration.resetScreenLayout(config.screenLayout);
3880        if (dm.widthPixels > dm.heightPixels) {
3881            config.orientation = Configuration.ORIENTATION_LANDSCAPE;
3882            config.screenLayout = Configuration.reduceScreenLayout(sl,
3883                    config.screenWidthDp, config.screenHeightDp);
3884        } else {
3885            config.orientation = Configuration.ORIENTATION_PORTRAIT;
3886            config.screenLayout = Configuration.reduceScreenLayout(sl,
3887                    config.screenHeightDp, config.screenWidthDp);
3888        }
3889        config.smallestScreenWidthDp = config.screenWidthDp; // assume screen does not rotate
3890        config.compatScreenWidthDp = config.screenWidthDp;
3891        config.compatScreenHeightDp = config.screenHeightDp;
3892        config.compatSmallestScreenWidthDp = config.smallestScreenWidthDp;
3893    }
3894
3895    final Configuration applyCompatConfiguration(int displayDensity) {
3896        Configuration config = mConfiguration;
3897        if (mCompatConfiguration == null) {
3898            mCompatConfiguration = new Configuration();
3899        }
3900        mCompatConfiguration.setTo(mConfiguration);
3901        if (mResCompatibilityInfo != null && !mResCompatibilityInfo.supportsScreen()) {
3902            mResCompatibilityInfo.applyToConfiguration(displayDensity, mCompatConfiguration);
3903            config = mCompatConfiguration;
3904        }
3905        return config;
3906    }
3907
3908    final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {
3909
3910        int configDiff = 0;
3911
3912        synchronized (mPackages) {
3913            if (mPendingConfiguration != null) {
3914                if (!mPendingConfiguration.isOtherSeqNewer(config)) {
3915                    config = mPendingConfiguration;
3916                    mCurDefaultDisplayDpi = config.densityDpi;
3917                    updateDefaultDensity();
3918                }
3919                mPendingConfiguration = null;
3920            }
3921
3922            if (config == null) {
3923                return;
3924            }
3925
3926            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: "
3927                    + config);
3928
3929            applyConfigurationToResourcesLocked(config, compat);
3930
3931            if (mConfiguration == null) {
3932                mConfiguration = new Configuration();
3933            }
3934            if (!mConfiguration.isOtherSeqNewer(config) && compat == null) {
3935                return;
3936            }
3937            configDiff = mConfiguration.diff(config);
3938            mConfiguration.updateFrom(config);
3939            config = applyCompatConfiguration(mCurDefaultDisplayDpi);
3940        }
3941
3942        ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
3943
3944        // Cleanup hardware accelerated stuff
3945        WindowManagerGlobal.getInstance().trimLocalMemory();
3946
3947        freeTextLayoutCachesIfNeeded(configDiff);
3948
3949        if (callbacks != null) {
3950            final int N = callbacks.size();
3951            for (int i=0; i<N; i++) {
3952                performConfigurationChanged(callbacks.get(i), config);
3953            }
3954        }
3955    }
3956
3957    final void freeTextLayoutCachesIfNeeded(int configDiff) {
3958        if (configDiff != 0) {
3959            // Ask text layout engine to free its caches if there is a locale change
3960            boolean hasLocaleConfigChange = ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0);
3961            if (hasLocaleConfigChange) {
3962                Canvas.freeTextLayoutCaches();
3963                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Cleared TextLayout Caches");
3964            }
3965        }
3966    }
3967
3968    final void handleActivityConfigurationChanged(IBinder token) {
3969        ActivityClientRecord r = mActivities.get(token);
3970        if (r == null || r.activity == null) {
3971            return;
3972        }
3973
3974        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
3975                + r.activityInfo.name);
3976
3977        performConfigurationChanged(r.activity, mCompatConfiguration);
3978
3979        freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(mCompatConfiguration));
3980    }
3981
3982    final void handleProfilerControl(boolean start, ProfilerControlData pcd, int profileType) {
3983        if (start) {
3984            try {
3985                switch (profileType) {
3986                    default:
3987                        mProfiler.setProfiler(pcd.path, pcd.fd);
3988                        mProfiler.autoStopProfiler = false;
3989                        mProfiler.startProfiling();
3990                        break;
3991                }
3992            } catch (RuntimeException e) {
3993                Slog.w(TAG, "Profiling failed on path " + pcd.path
3994                        + " -- can the process access this path?");
3995            } finally {
3996                try {
3997                    pcd.fd.close();
3998                } catch (IOException e) {
3999                    Slog.w(TAG, "Failure closing profile fd", e);
4000                }
4001            }
4002        } else {
4003            switch (profileType) {
4004                default:
4005                    mProfiler.stopProfiling();
4006                    break;
4007            }
4008        }
4009    }
4010
4011    static final void handleDumpHeap(boolean managed, DumpHeapData dhd) {
4012        if (managed) {
4013            try {
4014                Debug.dumpHprofData(dhd.path, dhd.fd.getFileDescriptor());
4015            } catch (IOException e) {
4016                Slog.w(TAG, "Managed heap dump failed on path " + dhd.path
4017                        + " -- can the process access this path?");
4018            } finally {
4019                try {
4020                    dhd.fd.close();
4021                } catch (IOException e) {
4022                    Slog.w(TAG, "Failure closing profile fd", e);
4023                }
4024            }
4025        } else {
4026            Debug.dumpNativeHeap(dhd.fd.getFileDescriptor());
4027        }
4028    }
4029
4030    final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
4031        boolean hasPkgInfo = false;
4032        if (packages != null) {
4033            for (int i=packages.length-1; i>=0; i--) {
4034                //Slog.i(TAG, "Cleaning old package: " + packages[i]);
4035                if (!hasPkgInfo) {
4036                    WeakReference<LoadedApk> ref;
4037                    ref = mPackages.get(packages[i]);
4038                    if (ref != null && ref.get() != null) {
4039                        hasPkgInfo = true;
4040                    } else {
4041                        ref = mResourcePackages.get(packages[i]);
4042                        if (ref != null && ref.get() != null) {
4043                            hasPkgInfo = true;
4044                        }
4045                    }
4046                }
4047                mPackages.remove(packages[i]);
4048                mResourcePackages.remove(packages[i]);
4049            }
4050        }
4051        ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
4052                hasPkgInfo);
4053    }
4054
4055    final void handleLowMemory() {
4056        ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
4057
4058        final int N = callbacks.size();
4059        for (int i=0; i<N; i++) {
4060            callbacks.get(i).onLowMemory();
4061        }
4062
4063        // Ask SQLite to free up as much memory as it can, mostly from its page caches.
4064        if (Process.myUid() != Process.SYSTEM_UID) {
4065            int sqliteReleased = SQLiteDatabase.releaseMemory();
4066            EventLog.writeEvent(SQLITE_MEM_RELEASED_EVENT_LOG_TAG, sqliteReleased);
4067        }
4068
4069        // Ask graphics to free up as much as possible (font/image caches)
4070        Canvas.freeCaches();
4071
4072        // Ask text layout engine to free also as much as possible
4073        Canvas.freeTextLayoutCaches();
4074
4075        BinderInternal.forceGc("mem");
4076    }
4077
4078    final void handleTrimMemory(int level) {
4079        if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level);
4080
4081        final WindowManagerGlobal windowManager = WindowManagerGlobal.getInstance();
4082        windowManager.startTrimMemory(level);
4083
4084        ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
4085
4086        final int N = callbacks.size();
4087        for (int i = 0; i < N; i++) {
4088            callbacks.get(i).onTrimMemory(level);
4089        }
4090
4091        windowManager.endTrimMemory();
4092    }
4093
4094    private void setupGraphicsSupport(LoadedApk info, File cacheDir) {
4095        if (Process.isIsolated()) {
4096            // Isolated processes aren't going to do UI.
4097            return;
4098        }
4099        try {
4100            int uid = Process.myUid();
4101            String[] packages = getPackageManager().getPackagesForUid(uid);
4102
4103            // If there are several packages in this application we won't
4104            // initialize the graphics disk caches
4105            if (packages != null && packages.length == 1) {
4106                HardwareRenderer.setupDiskCache(cacheDir);
4107                RenderScript.setupDiskCache(cacheDir);
4108            }
4109        } catch (RemoteException e) {
4110            // Ignore
4111        }
4112    }
4113
4114    private void updateDefaultDensity() {
4115        if (mCurDefaultDisplayDpi != Configuration.DENSITY_DPI_UNDEFINED
4116                && mCurDefaultDisplayDpi != DisplayMetrics.DENSITY_DEVICE
4117                && !mDensityCompatMode) {
4118            Slog.i(TAG, "Switching default density from "
4119                    + DisplayMetrics.DENSITY_DEVICE + " to "
4120                    + mCurDefaultDisplayDpi);
4121            DisplayMetrics.DENSITY_DEVICE = mCurDefaultDisplayDpi;
4122            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
4123        }
4124    }
4125
4126    private void handleBindApplication(AppBindData data) {
4127        mBoundApplication = data;
4128        mConfiguration = new Configuration(data.config);
4129        mCompatConfiguration = new Configuration(data.config);
4130
4131        mProfiler = new Profiler();
4132        mProfiler.profileFile = data.initProfileFile;
4133        mProfiler.profileFd = data.initProfileFd;
4134        mProfiler.autoStopProfiler = data.initAutoStopProfiler;
4135
4136        // send up app name; do this *before* waiting for debugger
4137        Process.setArgV0(data.processName);
4138        android.ddm.DdmHandleAppName.setAppName(data.processName,
4139                                                UserHandle.myUserId());
4140
4141        if (data.persistent) {
4142            // Persistent processes on low-memory devices do not get to
4143            // use hardware accelerated drawing, since this can add too much
4144            // overhead to the process.
4145            if (!ActivityManager.isHighEndGfx()) {
4146                HardwareRenderer.disable(false);
4147            }
4148        }
4149
4150        if (mProfiler.profileFd != null) {
4151            mProfiler.startProfiling();
4152        }
4153
4154        // If the app is Honeycomb MR1 or earlier, switch its AsyncTask
4155        // implementation to use the pool executor.  Normally, we use the
4156        // serialized executor as the default. This has to happen in the
4157        // main thread so the main looper is set right.
4158        if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
4159            AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
4160        }
4161
4162        /*
4163         * Before spawning a new process, reset the time zone to be the system time zone.
4164         * This needs to be done because the system time zone could have changed after the
4165         * the spawning of this process. Without doing this this process would have the incorrect
4166         * system time zone.
4167         */
4168        TimeZone.setDefault(null);
4169
4170        /*
4171         * Initialize the default locale in this process for the reasons we set the time zone.
4172         */
4173        Locale.setDefault(data.config.locale);
4174
4175        /*
4176         * Update the system configuration since its preloaded and might not
4177         * reflect configuration changes. The configuration object passed
4178         * in AppBindData can be safely assumed to be up to date
4179         */
4180        applyConfigurationToResourcesLocked(data.config, data.compatInfo);
4181        mCurDefaultDisplayDpi = data.config.densityDpi;
4182        applyCompatConfiguration(mCurDefaultDisplayDpi);
4183
4184        data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
4185
4186        /**
4187         * Switch this process to density compatibility mode if needed.
4188         */
4189        if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
4190                == 0) {
4191            mDensityCompatMode = true;
4192            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
4193        }
4194        updateDefaultDensity();
4195
4196        final ContextImpl appContext = new ContextImpl();
4197        appContext.init(data.info, null, this);
4198        if (!Process.isIsolated()) {
4199            final File cacheDir = appContext.getCacheDir();
4200
4201            if (cacheDir != null) {
4202                // Provide a usable directory for temporary files
4203                System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
4204
4205                setupGraphicsSupport(data.info, cacheDir);
4206            } else {
4207                Log.e(TAG, "Unable to setupGraphicsSupport due to missing cache directory");
4208            }
4209        }
4210        /**
4211         * For system applications on userdebug/eng builds, log stack
4212         * traces of disk and network access to dropbox for analysis.
4213         */
4214        if ((data.appInfo.flags &
4215             (ApplicationInfo.FLAG_SYSTEM |
4216              ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) {
4217            StrictMode.conditionallyEnableDebugLogging();
4218        }
4219
4220        /**
4221         * For apps targetting SDK Honeycomb or later, we don't allow
4222         * network usage on the main event loop / UI thread.
4223         *
4224         * Note to those grepping:  this is what ultimately throws
4225         * NetworkOnMainThreadException ...
4226         */
4227        if (data.appInfo.targetSdkVersion > 9) {
4228            StrictMode.enableDeathOnNetwork();
4229        }
4230
4231        if (data.debugMode != IApplicationThread.DEBUG_OFF) {
4232            // XXX should have option to change the port.
4233            Debug.changeDebugPort(8100);
4234            if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
4235                Slog.w(TAG, "Application " + data.info.getPackageName()
4236                      + " is waiting for the debugger on port 8100...");
4237
4238                IActivityManager mgr = ActivityManagerNative.getDefault();
4239                try {
4240                    mgr.showWaitingForDebugger(mAppThread, true);
4241                } catch (RemoteException ex) {
4242                }
4243
4244                Debug.waitForDebugger();
4245
4246                try {
4247                    mgr.showWaitingForDebugger(mAppThread, false);
4248                } catch (RemoteException ex) {
4249                }
4250
4251            } else {
4252                Slog.w(TAG, "Application " + data.info.getPackageName()
4253                      + " can be debugged on port 8100...");
4254            }
4255        }
4256
4257        // Enable OpenGL tracing if required
4258        if (data.enableOpenGlTrace) {
4259            GLUtils.enableTracing();
4260        }
4261
4262        /**
4263         * Initialize the default http proxy in this process for the reasons we set the time zone.
4264         */
4265        IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
4266        if (b != null) {
4267            // In pre-boot mode (doing initial launch to collect password), not
4268            // all system is up.  This includes the connectivity service, so don't
4269            // crash if we can't get it.
4270            IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
4271            try {
4272                ProxyProperties proxyProperties = service.getProxy();
4273                Proxy.setHttpProxySystemProperty(proxyProperties);
4274            } catch (RemoteException e) {}
4275        }
4276
4277        if (data.instrumentationName != null) {
4278            InstrumentationInfo ii = null;
4279            try {
4280                ii = appContext.getPackageManager().
4281                    getInstrumentationInfo(data.instrumentationName, 0);
4282            } catch (PackageManager.NameNotFoundException e) {
4283            }
4284            if (ii == null) {
4285                throw new RuntimeException(
4286                    "Unable to find instrumentation info for: "
4287                    + data.instrumentationName);
4288            }
4289
4290            mInstrumentationAppDir = ii.sourceDir;
4291            mInstrumentationAppLibraryDir = ii.nativeLibraryDir;
4292            mInstrumentationAppPackage = ii.packageName;
4293            mInstrumentedAppDir = data.info.getAppDir();
4294            mInstrumentedAppLibraryDir = data.info.getLibDir();
4295
4296            ApplicationInfo instrApp = new ApplicationInfo();
4297            instrApp.packageName = ii.packageName;
4298            instrApp.sourceDir = ii.sourceDir;
4299            instrApp.publicSourceDir = ii.publicSourceDir;
4300            instrApp.dataDir = ii.dataDir;
4301            instrApp.nativeLibraryDir = ii.nativeLibraryDir;
4302            LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
4303                    appContext.getClassLoader(), false, true);
4304            ContextImpl instrContext = new ContextImpl();
4305            instrContext.init(pi, null, this);
4306
4307            try {
4308                java.lang.ClassLoader cl = instrContext.getClassLoader();
4309                mInstrumentation = (Instrumentation)
4310                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
4311            } catch (Exception e) {
4312                throw new RuntimeException(
4313                    "Unable to instantiate instrumentation "
4314                    + data.instrumentationName + ": " + e.toString(), e);
4315            }
4316
4317            mInstrumentation.init(this, instrContext, appContext,
4318                    new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);
4319
4320            if (mProfiler.profileFile != null && !ii.handleProfiling
4321                    && mProfiler.profileFd == null) {
4322                mProfiler.handlingProfiling = true;
4323                File file = new File(mProfiler.profileFile);
4324                file.getParentFile().mkdirs();
4325                Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
4326            }
4327
4328        } else {
4329            mInstrumentation = new Instrumentation();
4330        }
4331
4332        if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
4333            dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
4334        }
4335
4336        // Allow disk access during application and provider setup. This could
4337        // block processing ordered broadcasts, but later processing would
4338        // probably end up doing the same disk access.
4339        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
4340        try {
4341            // If the app is being launched for full backup or restore, bring it up in
4342            // a restricted environment with the base application class.
4343            Application app = data.info.makeApplication(data.restrictedBackupMode, null);
4344            mInitialApplication = app;
4345
4346            // don't bring up providers in restricted mode; they may depend on the
4347            // app's custom Application class
4348            if (!data.restrictedBackupMode) {
4349                List<ProviderInfo> providers = data.providers;
4350                if (providers != null) {
4351                    installContentProviders(app, providers);
4352                    // For process that contains content providers, we want to
4353                    // ensure that the JIT is enabled "at some point".
4354                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
4355                }
4356            }
4357
4358            // Do this after providers, since instrumentation tests generally start their
4359            // test thread at this point, and we don't want that racing.
4360            try {
4361                mInstrumentation.onCreate(data.instrumentationArgs);
4362            }
4363            catch (Exception e) {
4364                throw new RuntimeException(
4365                    "Exception thrown in onCreate() of "
4366                    + data.instrumentationName + ": " + e.toString(), e);
4367            }
4368
4369            try {
4370                mInstrumentation.callApplicationOnCreate(app);
4371            } catch (Exception e) {
4372                if (!mInstrumentation.onException(app, e)) {
4373                    throw new RuntimeException(
4374                        "Unable to create application " + app.getClass().getName()
4375                        + ": " + e.toString(), e);
4376                }
4377            }
4378        } finally {
4379            StrictMode.setThreadPolicy(savedPolicy);
4380        }
4381    }
4382
4383    /*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
4384        IActivityManager am = ActivityManagerNative.getDefault();
4385        if (mProfiler.profileFile != null && mProfiler.handlingProfiling
4386                && mProfiler.profileFd == null) {
4387            Debug.stopMethodTracing();
4388        }
4389        //Slog.i(TAG, "am: " + ActivityManagerNative.getDefault()
4390        //      + ", app thr: " + mAppThread);
4391        try {
4392            am.finishInstrumentation(mAppThread, resultCode, results);
4393        } catch (RemoteException ex) {
4394        }
4395    }
4396
4397    private void installContentProviders(
4398            Context context, List<ProviderInfo> providers) {
4399        final ArrayList<IActivityManager.ContentProviderHolder> results =
4400            new ArrayList<IActivityManager.ContentProviderHolder>();
4401
4402        for (ProviderInfo cpi : providers) {
4403            StringBuilder buf = new StringBuilder(128);
4404            buf.append("Pub ");
4405            buf.append(cpi.authority);
4406            buf.append(": ");
4407            buf.append(cpi.name);
4408            Log.i(TAG, buf.toString());
4409            IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
4410                    false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
4411            if (cph != null) {
4412                cph.noReleaseNeeded = true;
4413                results.add(cph);
4414            }
4415        }
4416
4417        try {
4418            ActivityManagerNative.getDefault().publishContentProviders(
4419                getApplicationThread(), results);
4420        } catch (RemoteException ex) {
4421        }
4422    }
4423
4424    public final IContentProvider acquireProvider(
4425            Context c, String auth, int userId, boolean stable) {
4426        final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
4427        if (provider != null) {
4428            return provider;
4429        }
4430
4431        // There is a possible race here.  Another thread may try to acquire
4432        // the same provider at the same time.  When this happens, we want to ensure
4433        // that the first one wins.
4434        // Note that we cannot hold the lock while acquiring and installing the
4435        // provider since it might take a long time to run and it could also potentially
4436        // be re-entrant in the case where the provider is in the same process.
4437        IActivityManager.ContentProviderHolder holder = null;
4438        try {
4439            holder = ActivityManagerNative.getDefault().getContentProvider(
4440                    getApplicationThread(), auth, userId, stable);
4441        } catch (RemoteException ex) {
4442        }
4443        if (holder == null) {
4444            Slog.e(TAG, "Failed to find provider info for " + auth);
4445            return null;
4446        }
4447
4448        // Install provider will increment the reference count for us, and break
4449        // any ties in the race.
4450        holder = installProvider(c, holder, holder.info,
4451                true /*noisy*/, holder.noReleaseNeeded, stable);
4452        return holder.provider;
4453    }
4454
4455    private final void incProviderRefLocked(ProviderRefCount prc, boolean stable) {
4456        if (stable) {
4457            prc.stableCount += 1;
4458            if (prc.stableCount == 1) {
4459                // We are acquiring a new stable reference on the provider.
4460                int unstableDelta;
4461                if (prc.removePending) {
4462                    // We have a pending remove operation, which is holding the
4463                    // last unstable reference.  At this point we are converting
4464                    // that unstable reference to our new stable reference.
4465                    unstableDelta = -1;
4466                    // Cancel the removal of the provider.
4467                    if (DEBUG_PROVIDER) {
4468                        Slog.v(TAG, "incProviderRef: stable "
4469                                + "snatched provider from the jaws of death");
4470                    }
4471                    prc.removePending = false;
4472                    mH.removeMessages(H.REMOVE_PROVIDER, prc);
4473                } else {
4474                    unstableDelta = 0;
4475                }
4476                try {
4477                    if (DEBUG_PROVIDER) {
4478                        Slog.v(TAG, "incProviderRef Now stable - "
4479                                + prc.holder.info.name + ": unstableDelta="
4480                                + unstableDelta);
4481                    }
4482                    ActivityManagerNative.getDefault().refContentProvider(
4483                            prc.holder.connection, 1, unstableDelta);
4484                } catch (RemoteException e) {
4485                    //do nothing content provider object is dead any way
4486                }
4487            }
4488        } else {
4489            prc.unstableCount += 1;
4490            if (prc.unstableCount == 1) {
4491                // We are acquiring a new unstable reference on the provider.
4492                if (prc.removePending) {
4493                    // Oh look, we actually have a remove pending for the
4494                    // provider, which is still holding the last unstable
4495                    // reference.  We just need to cancel that to take new
4496                    // ownership of the reference.
4497                    if (DEBUG_PROVIDER) {
4498                        Slog.v(TAG, "incProviderRef: unstable "
4499                                + "snatched provider from the jaws of death");
4500                    }
4501                    prc.removePending = false;
4502                    mH.removeMessages(H.REMOVE_PROVIDER, prc);
4503                } else {
4504                    // First unstable ref, increment our count in the
4505                    // activity manager.
4506                    try {
4507                        if (DEBUG_PROVIDER) {
4508                            Slog.v(TAG, "incProviderRef: Now unstable - "
4509                                    + prc.holder.info.name);
4510                        }
4511                        ActivityManagerNative.getDefault().refContentProvider(
4512                                prc.holder.connection, 0, 1);
4513                    } catch (RemoteException e) {
4514                        //do nothing content provider object is dead any way
4515                    }
4516                }
4517            }
4518        }
4519    }
4520
4521    public final IContentProvider acquireExistingProvider(
4522            Context c, String auth, int userId, boolean stable) {
4523        synchronized (mProviderMap) {
4524            final ProviderKey key = new ProviderKey(auth, userId);
4525            final ProviderClientRecord pr = mProviderMap.get(key);
4526            if (pr == null) {
4527                return null;
4528            }
4529
4530            IContentProvider provider = pr.mProvider;
4531            IBinder jBinder = provider.asBinder();
4532
4533            // Only increment the ref count if we have one.  If we don't then the
4534            // provider is not reference counted and never needs to be released.
4535            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4536            if (prc != null) {
4537                incProviderRefLocked(prc, stable);
4538            }
4539            return provider;
4540        }
4541    }
4542
4543    public final boolean releaseProvider(IContentProvider provider, boolean stable) {
4544        if (provider == null) {
4545            return false;
4546        }
4547
4548        IBinder jBinder = provider.asBinder();
4549        synchronized (mProviderMap) {
4550            ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4551            if (prc == null) {
4552                // The provider has no ref count, no release is needed.
4553                return false;
4554            }
4555
4556            boolean lastRef = false;
4557            if (stable) {
4558                if (prc.stableCount == 0) {
4559                    if (DEBUG_PROVIDER) Slog.v(TAG,
4560                            "releaseProvider: stable ref count already 0, how?");
4561                    return false;
4562                }
4563                prc.stableCount -= 1;
4564                if (prc.stableCount == 0) {
4565                    // What we do at this point depends on whether there are
4566                    // any unstable refs left: if there are, we just tell the
4567                    // activity manager to decrement its stable count; if there
4568                    // aren't, we need to enqueue this provider to be removed,
4569                    // and convert to holding a single unstable ref while
4570                    // doing so.
4571                    lastRef = prc.unstableCount == 0;
4572                    try {
4573                        if (DEBUG_PROVIDER) {
4574                            Slog.v(TAG, "releaseProvider: No longer stable w/lastRef="
4575                                    + lastRef + " - " + prc.holder.info.name);
4576                        }
4577                        ActivityManagerNative.getDefault().refContentProvider(
4578                                prc.holder.connection, -1, lastRef ? 1 : 0);
4579                    } catch (RemoteException e) {
4580                        //do nothing content provider object is dead any way
4581                    }
4582                }
4583            } else {
4584                if (prc.unstableCount == 0) {
4585                    if (DEBUG_PROVIDER) Slog.v(TAG,
4586                            "releaseProvider: unstable ref count already 0, how?");
4587                    return false;
4588                }
4589                prc.unstableCount -= 1;
4590                if (prc.unstableCount == 0) {
4591                    // If this is the last reference, we need to enqueue
4592                    // this provider to be removed instead of telling the
4593                    // activity manager to remove it at this point.
4594                    lastRef = prc.stableCount == 0;
4595                    if (!lastRef) {
4596                        try {
4597                            if (DEBUG_PROVIDER) {
4598                                Slog.v(TAG, "releaseProvider: No longer unstable - "
4599                                        + prc.holder.info.name);
4600                            }
4601                            ActivityManagerNative.getDefault().refContentProvider(
4602                                    prc.holder.connection, 0, -1);
4603                        } catch (RemoteException e) {
4604                            //do nothing content provider object is dead any way
4605                        }
4606                    }
4607                }
4608            }
4609
4610            if (lastRef) {
4611                if (!prc.removePending) {
4612                    // Schedule the actual remove asynchronously, since we don't know the context
4613                    // this will be called in.
4614                    // TODO: it would be nice to post a delayed message, so
4615                    // if we come back and need the same provider quickly
4616                    // we will still have it available.
4617                    if (DEBUG_PROVIDER) {
4618                        Slog.v(TAG, "releaseProvider: Enqueueing pending removal - "
4619                                + prc.holder.info.name);
4620                    }
4621                    prc.removePending = true;
4622                    Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, prc);
4623                    mH.sendMessage(msg);
4624                } else {
4625                    Slog.w(TAG, "Duplicate remove pending of provider " + prc.holder.info.name);
4626                }
4627            }
4628            return true;
4629        }
4630    }
4631
4632    final void completeRemoveProvider(ProviderRefCount prc) {
4633        synchronized (mProviderMap) {
4634            if (!prc.removePending) {
4635                // There was a race!  Some other client managed to acquire
4636                // the provider before the removal was completed.
4637                // Abort the removal.  We will do it later.
4638                if (DEBUG_PROVIDER) Slog.v(TAG, "completeRemoveProvider: lost the race, "
4639                        + "provider still in use");
4640                return;
4641            }
4642
4643            final IBinder jBinder = prc.holder.provider.asBinder();
4644            ProviderRefCount existingPrc = mProviderRefCountMap.get(jBinder);
4645            if (existingPrc == prc) {
4646                mProviderRefCountMap.remove(jBinder);
4647            }
4648
4649            Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator();
4650            while (iter.hasNext()) {
4651                ProviderClientRecord pr = iter.next();
4652                IBinder myBinder = pr.mProvider.asBinder();
4653                if (myBinder == jBinder) {
4654                    iter.remove();
4655                }
4656            }
4657        }
4658
4659        try {
4660            if (DEBUG_PROVIDER) {
4661                Slog.v(TAG, "removeProvider: Invoking ActivityManagerNative."
4662                        + "removeContentProvider(" + prc.holder.info.name + ")");
4663            }
4664            ActivityManagerNative.getDefault().removeContentProvider(
4665                    prc.holder.connection, false);
4666        } catch (RemoteException e) {
4667            //do nothing content provider object is dead any way
4668        }
4669    }
4670
4671    final void handleUnstableProviderDied(IBinder provider, boolean fromClient) {
4672        synchronized(mProviderMap) {
4673            ProviderRefCount prc = mProviderRefCountMap.get(provider);
4674            if (prc != null) {
4675                if (DEBUG_PROVIDER) Slog.v(TAG, "Cleaning up dead provider "
4676                        + provider + " " + prc.holder.info.name);
4677                mProviderRefCountMap.remove(provider);
4678                if (prc.client != null && prc.client.mNames != null) {
4679                    for (String name : prc.client.mNames) {
4680                        ProviderClientRecord pr = mProviderMap.get(name);
4681                        if (pr != null && pr.mProvider.asBinder() == provider) {
4682                            Slog.i(TAG, "Removing dead content provider: " + name);
4683                            mProviderMap.remove(name);
4684                        }
4685                    }
4686                }
4687                if (fromClient) {
4688                    // We found out about this due to execution in our client
4689                    // code.  Tell the activity manager about it now, to ensure
4690                    // that the next time we go to do anything with the provider
4691                    // it knows it is dead (so we don't race with its death
4692                    // notification).
4693                    try {
4694                        ActivityManagerNative.getDefault().unstableProviderDied(
4695                                prc.holder.connection);
4696                    } catch (RemoteException e) {
4697                        //do nothing content provider object is dead any way
4698                    }
4699                }
4700            }
4701        }
4702    }
4703
4704    private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider,
4705            ContentProvider localProvider, IActivityManager.ContentProviderHolder holder) {
4706        final String auths[] = PATTERN_SEMICOLON.split(holder.info.authority);
4707        final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid);
4708
4709        final ProviderClientRecord pcr = new ProviderClientRecord(
4710                auths, provider, localProvider, holder);
4711        for (String auth : auths) {
4712            final ProviderKey key = new ProviderKey(auth, userId);
4713            final ProviderClientRecord existing = mProviderMap.get(key);
4714            if (existing != null) {
4715                Slog.w(TAG, "Content provider " + pcr.mHolder.info.name
4716                        + " already published as " + auth);
4717            } else {
4718                mProviderMap.put(key, pcr);
4719            }
4720        }
4721        return pcr;
4722    }
4723
4724    /**
4725     * Installs the provider.
4726     *
4727     * Providers that are local to the process or that come from the system server
4728     * may be installed permanently which is indicated by setting noReleaseNeeded to true.
4729     * Other remote providers are reference counted.  The initial reference count
4730     * for all reference counted providers is one.  Providers that are not reference
4731     * counted do not have a reference count (at all).
4732     *
4733     * This method detects when a provider has already been installed.  When this happens,
4734     * it increments the reference count of the existing provider (if appropriate)
4735     * and returns the existing provider.  This can happen due to concurrent
4736     * attempts to acquire the same provider.
4737     */
4738    private IActivityManager.ContentProviderHolder installProvider(Context context,
4739            IActivityManager.ContentProviderHolder holder, ProviderInfo info,
4740            boolean noisy, boolean noReleaseNeeded, boolean stable) {
4741        ContentProvider localProvider = null;
4742        IContentProvider provider;
4743        if (holder == null || holder.provider == null) {
4744            if (DEBUG_PROVIDER || noisy) {
4745                Slog.d(TAG, "Loading provider " + info.authority + ": "
4746                        + info.name);
4747            }
4748            Context c = null;
4749            ApplicationInfo ai = info.applicationInfo;
4750            if (context.getPackageName().equals(ai.packageName)) {
4751                c = context;
4752            } else if (mInitialApplication != null &&
4753                    mInitialApplication.getPackageName().equals(ai.packageName)) {
4754                c = mInitialApplication;
4755            } else {
4756                try {
4757                    c = context.createPackageContext(ai.packageName,
4758                            Context.CONTEXT_INCLUDE_CODE);
4759                } catch (PackageManager.NameNotFoundException e) {
4760                    // Ignore
4761                }
4762            }
4763            if (c == null) {
4764                Slog.w(TAG, "Unable to get context for package " +
4765                      ai.packageName +
4766                      " while loading content provider " +
4767                      info.name);
4768                return null;
4769            }
4770            try {
4771                final java.lang.ClassLoader cl = c.getClassLoader();
4772                localProvider = (ContentProvider)cl.
4773                    loadClass(info.name).newInstance();
4774                provider = localProvider.getIContentProvider();
4775                if (provider == null) {
4776                    Slog.e(TAG, "Failed to instantiate class " +
4777                          info.name + " from sourceDir " +
4778                          info.applicationInfo.sourceDir);
4779                    return null;
4780                }
4781                if (DEBUG_PROVIDER) Slog.v(
4782                    TAG, "Instantiating local provider " + info.name);
4783                // XXX Need to create the correct context for this provider.
4784                localProvider.attachInfo(c, info);
4785            } catch (java.lang.Exception e) {
4786                if (!mInstrumentation.onException(null, e)) {
4787                    throw new RuntimeException(
4788                            "Unable to get provider " + info.name
4789                            + ": " + e.toString(), e);
4790                }
4791                return null;
4792            }
4793        } else {
4794            provider = holder.provider;
4795            if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": "
4796                    + info.name);
4797        }
4798
4799        IActivityManager.ContentProviderHolder retHolder;
4800
4801        synchronized (mProviderMap) {
4802            if (DEBUG_PROVIDER) Slog.v(TAG, "Checking to add " + provider
4803                    + " / " + info.name);
4804            IBinder jBinder = provider.asBinder();
4805            if (localProvider != null) {
4806                ComponentName cname = new ComponentName(info.packageName, info.name);
4807                ProviderClientRecord pr = mLocalProvidersByName.get(cname);
4808                if (pr != null) {
4809                    if (DEBUG_PROVIDER) {
4810                        Slog.v(TAG, "installProvider: lost the race, "
4811                                + "using existing local provider");
4812                    }
4813                    provider = pr.mProvider;
4814                } else {
4815                    holder = new IActivityManager.ContentProviderHolder(info);
4816                    holder.provider = provider;
4817                    holder.noReleaseNeeded = true;
4818                    pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
4819                    mLocalProviders.put(jBinder, pr);
4820                    mLocalProvidersByName.put(cname, pr);
4821                }
4822                retHolder = pr.mHolder;
4823            } else {
4824                ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
4825                if (prc != null) {
4826                    if (DEBUG_PROVIDER) {
4827                        Slog.v(TAG, "installProvider: lost the race, updating ref count");
4828                    }
4829                    // We need to transfer our new reference to the existing
4830                    // ref count, releasing the old one...  but only if
4831                    // release is needed (that is, it is not running in the
4832                    // system process).
4833                    if (!noReleaseNeeded) {
4834                        incProviderRefLocked(prc, stable);
4835                        try {
4836                            ActivityManagerNative.getDefault().removeContentProvider(
4837                                    holder.connection, stable);
4838                        } catch (RemoteException e) {
4839                            //do nothing content provider object is dead any way
4840                        }
4841                    }
4842                } else {
4843                    ProviderClientRecord client = installProviderAuthoritiesLocked(
4844                            provider, localProvider, holder);
4845                    if (noReleaseNeeded) {
4846                        prc = new ProviderRefCount(holder, client, 1000, 1000);
4847                    } else {
4848                        prc = stable
4849                                ? new ProviderRefCount(holder, client, 1, 0)
4850                                : new ProviderRefCount(holder, client, 0, 1);
4851                    }
4852                    mProviderRefCountMap.put(jBinder, prc);
4853                }
4854                retHolder = prc.holder;
4855            }
4856        }
4857
4858        return retHolder;
4859    }
4860
4861    private void attach(boolean system) {
4862        sThreadLocal.set(this);
4863        mSystemThread = system;
4864        if (!system) {
4865            ViewRootImpl.addFirstDrawHandler(new Runnable() {
4866                public void run() {
4867                    ensureJitEnabled();
4868                }
4869            });
4870            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
4871                                                    UserHandle.myUserId());
4872            RuntimeInit.setApplicationObject(mAppThread.asBinder());
4873            IActivityManager mgr = ActivityManagerNative.getDefault();
4874            try {
4875                mgr.attachApplication(mAppThread);
4876            } catch (RemoteException ex) {
4877                // Ignore
4878            }
4879        } else {
4880            // Don't set application object here -- if the system crashes,
4881            // we can't display an alert, we just want to die die die.
4882            android.ddm.DdmHandleAppName.setAppName("system_process",
4883                                                    UserHandle.myUserId());
4884            try {
4885                mInstrumentation = new Instrumentation();
4886                ContextImpl context = new ContextImpl();
4887                context.init(getSystemContext().mPackageInfo, null, this);
4888                Application app = Instrumentation.newApplication(Application.class, context);
4889                mAllApplications.add(app);
4890                mInitialApplication = app;
4891                app.onCreate();
4892            } catch (Exception e) {
4893                throw new RuntimeException(
4894                        "Unable to instantiate Application():" + e.toString(), e);
4895            }
4896        }
4897
4898        // add dropbox logging to libcore
4899        DropBox.setReporter(new DropBoxReporter());
4900
4901        ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
4902            public void onConfigurationChanged(Configuration newConfig) {
4903                synchronized (mPackages) {
4904                    // We need to apply this change to the resources
4905                    // immediately, because upon returning the view
4906                    // hierarchy will be informed about it.
4907                    if (applyConfigurationToResourcesLocked(newConfig, null)) {
4908                        // This actually changed the resources!  Tell
4909                        // everyone about it.
4910                        if (mPendingConfiguration == null ||
4911                                mPendingConfiguration.isOtherSeqNewer(newConfig)) {
4912                            mPendingConfiguration = newConfig;
4913
4914                            queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
4915                        }
4916                    }
4917                }
4918            }
4919            public void onLowMemory() {
4920            }
4921            public void onTrimMemory(int level) {
4922            }
4923        });
4924    }
4925
4926    public static ActivityThread systemMain() {
4927        HardwareRenderer.disable(true);
4928        ActivityThread thread = new ActivityThread();
4929        thread.attach(true);
4930        return thread;
4931    }
4932
4933    public final void installSystemProviders(List<ProviderInfo> providers) {
4934        if (providers != null) {
4935            installContentProviders(mInitialApplication, providers);
4936        }
4937    }
4938
4939    public int getIntCoreSetting(String key, int defaultValue) {
4940        synchronized (mPackages) {
4941            if (mCoreSettings != null) {
4942                return mCoreSettings.getInt(key, defaultValue);
4943            } else {
4944                return defaultValue;
4945            }
4946        }
4947    }
4948
4949    private class DropBoxReporter implements DropBox.Reporter {
4950
4951        private DropBoxManager dropBox;
4952
4953        public DropBoxReporter() {
4954            dropBox = (DropBoxManager) getSystemContext().getSystemService(Context.DROPBOX_SERVICE);
4955        }
4956
4957        @Override
4958        public void addData(String tag, byte[] data, int flags) {
4959            dropBox.addData(tag, data, flags);
4960        }
4961
4962        @Override
4963        public void addText(String tag, String data) {
4964            dropBox.addText(tag, data);
4965        }
4966    }
4967
4968    public static void main(String[] args) {
4969        SamplingProfilerIntegration.start();
4970
4971        // CloseGuard defaults to true and can be quite spammy.  We
4972        // disable it here, but selectively enable it later (via
4973        // StrictMode) on debug builds, but using DropBox, not logs.
4974        CloseGuard.setEnabled(false);
4975
4976        Environment.initForCurrentUser();
4977
4978        Process.setArgV0("<pre-initialized>");
4979
4980        Looper.prepareMainLooper();
4981
4982        ActivityThread thread = new ActivityThread();
4983        thread.attach(false);
4984
4985        if (sMainThreadHandler == null) {
4986            sMainThreadHandler = thread.getHandler();
4987        }
4988
4989        AsyncTask.init();
4990
4991        if (false) {
4992            Looper.myLooper().setMessageLogging(new
4993                    LogPrinter(Log.DEBUG, "ActivityThread"));
4994        }
4995
4996        Looper.loop();
4997
4998        throw new RuntimeException("Main thread loop unexpectedly exited");
4999    }
5000}
5001