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