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