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