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