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