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