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