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