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