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