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