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