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