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.Handler;
66import android.os.IBinder;
67import android.os.LocaleList;
68import android.os.Looper;
69import android.os.Message;
70import android.os.MessageQueue;
71import android.os.Parcel;
72import android.os.ParcelFileDescriptor;
73import android.os.PersistableBundle;
74import android.os.Process;
75import android.os.RemoteException;
76import android.os.ServiceManager;
77import android.os.StrictMode;
78import android.os.SystemClock;
79import android.os.SystemProperties;
80import android.os.Trace;
81import android.os.TransactionTooLargeException;
82import android.os.UserHandle;
83import android.provider.Settings;
84import android.security.NetworkSecurityPolicy;
85import android.security.net.config.NetworkSecurityConfigProvider;
86import android.util.AndroidRuntimeException;
87import android.util.ArrayMap;
88import android.util.DisplayMetrics;
89import android.util.EventLog;
90import android.util.Log;
91import android.util.LogPrinter;
92import android.util.Pair;
93import android.util.PrintWriterPrinter;
94import android.util.Slog;
95import android.util.SparseIntArray;
96import android.util.SuperNotCalledException;
97import android.view.ContextThemeWrapper;
98import android.view.Display;
99import android.view.ThreadedRenderer;
100import android.view.View;
101import android.view.ViewDebug;
102import android.view.ViewManager;
103import android.view.ViewRootImpl;
104import android.view.Window;
105import android.view.WindowManager;
106import android.view.WindowManagerGlobal;
107import android.renderscript.RenderScriptCacheDir;
108import android.system.Os;
109import android.system.OsConstants;
110import android.system.ErrnoException;
111
112import com.android.internal.annotations.GuardedBy;
113import com.android.internal.app.IVoiceInteractor;
114import com.android.internal.content.ReferrerIntent;
115import com.android.internal.os.BinderInternal;
116import com.android.internal.os.RuntimeInit;
117import com.android.internal.os.SamplingProfilerIntegration;
118import com.android.internal.os.SomeArgs;
119import com.android.internal.util.ArrayUtils;
120import com.android.internal.util.FastPrintWriter;
121import com.android.org.conscrypt.OpenSSLSocketImpl;
122import com.android.org.conscrypt.TrustedCertificateStore;
123import com.google.android.collect.Lists;
124
125import java.io.File;
126import java.io.FileDescriptor;
127import java.io.FileOutputStream;
128import java.io.IOException;
129import java.io.PrintWriter;
130import java.lang.ref.WeakReference;
131import java.net.InetAddress;
132import java.text.DateFormat;
133import java.util.ArrayList;
134import java.util.Collections;
135import java.util.List;
136import java.util.Locale;
137import java.util.Map;
138import java.util.Objects;
139import java.util.TimeZone;
140
141import libcore.io.DropBox;
142import libcore.io.EventLogger;
143import libcore.io.IoUtils;
144import libcore.net.event.NetworkEventDispatcher;
145import dalvik.system.CloseGuard;
146import dalvik.system.VMDebug;
147import dalvik.system.VMRuntime;
148import org.apache.harmony.dalvik.ddmc.DdmVmInternal;
149
150final class RemoteServiceException extends AndroidRuntimeException {
151    public RemoteServiceException(String msg) {
152        super(msg);
153    }
154}
155
156/**
157 * This manages the execution of the main thread in an
158 * application process, scheduling and executing activities,
159 * broadcasts, and other operations on it as the activity
160 * manager requests.
161 *
162 * {@hide}
163 */
164public final class ActivityThread {
165    /** @hide */
166    public static final String TAG = "ActivityThread";
167    private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
168    static final boolean localLOGV = false;
169    static final boolean DEBUG_MESSAGES = false;
170    /** @hide */
171    public static final boolean DEBUG_BROADCAST = false;
172    private static final boolean DEBUG_RESULTS = false;
173    private static final boolean DEBUG_BACKUP = false;
174    public static final boolean DEBUG_CONFIGURATION = false;
175    private static final boolean DEBUG_SERVICE = false;
176    private static final boolean DEBUG_MEMORY_TRIM = false;
177    private static final boolean DEBUG_PROVIDER = false;
178    private static final boolean DEBUG_ORDER = false;
179    private static final long MIN_TIME_BETWEEN_GCS = 5*1000;
180    private static final int SQLITE_MEM_RELEASED_EVENT_LOG_TAG = 75003;
181    private static final int LOG_AM_ON_PAUSE_CALLED = 30021;
182    private static final int LOG_AM_ON_RESUME_CALLED = 30022;
183    private static final int LOG_AM_ON_STOP_CALLED = 30049;
184
185    /** Type for IActivityManager.serviceDoneExecuting: anonymous operation */
186    public static final int SERVICE_DONE_EXECUTING_ANON = 0;
187    /** Type for IActivityManager.serviceDoneExecuting: done with an onStart call */
188    public static final int SERVICE_DONE_EXECUTING_START = 1;
189    /** Type for IActivityManager.serviceDoneExecuting: done stopping (destroying) service */
190    public static final int SERVICE_DONE_EXECUTING_STOP = 2;
191
192    // Details for pausing activity.
193    private static final int USER_LEAVING = 1;
194    private static final int DONT_REPORT = 2;
195
196    // Whether to invoke an activity callback after delivering new configuration.
197    private static final boolean REPORT_TO_ACTIVITY = true;
198
199    private ContextImpl mSystemContext;
200
201    static volatile IPackageManager sPackageManager;
202
203    final ApplicationThread mAppThread = new ApplicationThread();
204    final Looper mLooper = Looper.myLooper();
205    final H mH = new H();
206    final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
207    // List of new activities (via ActivityRecord.nextIdle) that should
208    // be reported when next we idle.
209    ActivityClientRecord mNewActivities = null;
210    // Number of activities that are currently visible on-screen.
211    int mNumVisibleActivities = 0;
212    ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>();
213    private int mLastSessionId;
214    final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
215    AppBindData mBoundApplication;
216    Profiler mProfiler;
217    int mCurDefaultDisplayDpi;
218    boolean mDensityCompatMode;
219    Configuration mConfiguration;
220    Configuration mCompatConfiguration;
221    Application mInitialApplication;
222    final ArrayList<Application> mAllApplications
223            = new ArrayList<Application>();
224    // set of instantiated backup agents, keyed by package name
225    final ArrayMap<String, BackupAgent> mBackupAgents = new ArrayMap<String, BackupAgent>();
226    /** Reference to singleton {@link ActivityThread} */
227    private static volatile ActivityThread sCurrentActivityThread;
228    Instrumentation mInstrumentation;
229    String mInstrumentationPackageName = null;
230    String mInstrumentationAppDir = null;
231    String[] mInstrumentationSplitAppDirs = null;
232    String mInstrumentationLibDir = null;
233    String mInstrumentedAppDir = null;
234    String[] mInstrumentedSplitAppDirs = null;
235    String mInstrumentedLibDir = null;
236    boolean mSystemThread = false;
237    boolean mJitEnabled = false;
238    boolean mSomeActivitiesChanged = false;
239
240    // These can be accessed by multiple threads; mPackages is the lock.
241    // XXX For now we keep around information about all packages we have
242    // seen, not removing entries from this map.
243    // NOTE: The activity and window managers need to call in to
244    // ActivityThread to do things like update resource configurations,
245    // which means this lock gets held while the activity and window managers
246    // holds their own lock.  Thus you MUST NEVER call back into the activity manager
247    // or window manager or anything that depends on them while holding this lock.
248    // These LoadedApk are only valid for the userId that we're running as.
249    final ArrayMap<String, WeakReference<LoadedApk>> mPackages
250            = new ArrayMap<String, WeakReference<LoadedApk>>();
251    final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages
252            = new ArrayMap<String, WeakReference<LoadedApk>>();
253    final ArrayList<ActivityClientRecord> mRelaunchingActivities
254            = new ArrayList<ActivityClientRecord>();
255    Configuration mPendingConfiguration = null;
256    // Because we merge activity relaunch operations we can't depend on the ordering provided by
257    // the handler messages. We need to introduce secondary ordering mechanism, which will allow
258    // us to drop certain events, if we know that they happened before relaunch we already executed.
259    // This represents the order of receiving the request from AM.
260    @GuardedBy("mResourcesManager")
261    int mLifecycleSeq = 0;
262
263    private final ResourcesManager mResourcesManager;
264
265    private static final class ProviderKey {
266        final String authority;
267        final int userId;
268
269        public ProviderKey(String authority, int userId) {
270            this.authority = authority;
271            this.userId = userId;
272        }
273
274        @Override
275        public boolean equals(Object o) {
276            if (o instanceof ProviderKey) {
277                final ProviderKey other = (ProviderKey) o;
278                return Objects.equals(authority, other.authority) && userId == other.userId;
279            }
280            return false;
281        }
282
283        @Override
284        public int hashCode() {
285            return ((authority != null) ? authority.hashCode() : 0) ^ userId;
286        }
287    }
288
289    // The lock of mProviderMap protects the following variables.
290    final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap
291        = new ArrayMap<ProviderKey, ProviderClientRecord>();
292    final ArrayMap<IBinder, ProviderRefCount> mProviderRefCountMap
293        = new ArrayMap<IBinder, ProviderRefCount>();
294    final ArrayMap<IBinder, ProviderClientRecord> mLocalProviders
295        = new ArrayMap<IBinder, ProviderClientRecord>();
296    final ArrayMap<ComponentName, ProviderClientRecord> mLocalProvidersByName
297            = new ArrayMap<ComponentName, ProviderClientRecord>();
298
299    final ArrayMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners
300        = new ArrayMap<Activity, ArrayList<OnActivityPausedListener>>();
301
302    final GcIdler mGcIdler = new GcIdler();
303    boolean mGcIdlerScheduled = false;
304
305    static volatile Handler sMainThreadHandler;  // set once in main()
306
307    Bundle mCoreSettings = null;
308
309    static final class ActivityClientRecord {
310        IBinder token;
311        int ident;
312        Intent intent;
313        String referrer;
314        IVoiceInteractor voiceInteractor;
315        Bundle state;
316        PersistableBundle persistentState;
317        Activity activity;
318        Window window;
319        Activity parent;
320        String embeddedID;
321        Activity.NonConfigurationInstances lastNonConfigurationInstances;
322        boolean paused;
323        boolean stopped;
324        boolean hideForNow;
325        Configuration newConfig;
326        Configuration createdConfig;
327        Configuration overrideConfig;
328        // Used for consolidating configs before sending on to Activity.
329        private Configuration tmpConfig = new Configuration();
330        ActivityClientRecord nextIdle;
331
332        ProfilerInfo profilerInfo;
333
334        ActivityInfo activityInfo;
335        CompatibilityInfo compatInfo;
336        LoadedApk packageInfo;
337
338        List<ResultInfo> pendingResults;
339        List<ReferrerIntent> pendingIntents;
340
341        boolean startsNotResumed;
342        boolean isForward;
343        int pendingConfigChanges;
344        boolean onlyLocalRequest;
345
346        Window mPendingRemoveWindow;
347        WindowManager mPendingRemoveWindowManager;
348        boolean mPreserveWindow;
349
350        // Set for relaunch requests, indicates the order number of the relaunch operation, so it
351        // can be compared with other lifecycle operations.
352        int relaunchSeq = 0;
353
354        // Can only be accessed from the UI thread. This represents the latest processed message
355        // that is related to lifecycle events/
356        int lastProcessedSeq = 0;
357
358        ActivityClientRecord() {
359            parent = null;
360            embeddedID = null;
361            paused = false;
362            stopped = false;
363            hideForNow = false;
364            nextIdle = null;
365        }
366
367        public boolean isPreHoneycomb() {
368            if (activity != null) {
369                return activity.getApplicationInfo().targetSdkVersion
370                        < android.os.Build.VERSION_CODES.HONEYCOMB;
371            }
372            return false;
373        }
374
375        public boolean isPersistable() {
376            return activityInfo.persistableMode == ActivityInfo.PERSIST_ACROSS_REBOOTS;
377        }
378
379        public String toString() {
380            ComponentName componentName = intent != null ? intent.getComponent() : null;
381            return "ActivityRecord{"
382                + Integer.toHexString(System.identityHashCode(this))
383                + " token=" + token + " " + (componentName == null
384                        ? "no component name" : componentName.toShortString())
385                + "}";
386        }
387
388        public String getStateString() {
389            StringBuilder sb = new StringBuilder();
390            sb.append("ActivityClientRecord{");
391            sb.append("paused=").append(paused);
392            sb.append(", stopped=").append(stopped);
393            sb.append(", hideForNow=").append(hideForNow);
394            sb.append(", startsNotResumed=").append(startsNotResumed);
395            sb.append(", isForward=").append(isForward);
396            sb.append(", pendingConfigChanges=").append(pendingConfigChanges);
397            sb.append(", onlyLocalRequest=").append(onlyLocalRequest);
398            sb.append(", preserveWindow=").append(mPreserveWindow);
399            if (activity != null) {
400                sb.append(", Activity{");
401                sb.append("resumed=").append(activity.mResumed);
402                sb.append(", stopped=").append(activity.mStopped);
403                sb.append(", finished=").append(activity.isFinishing());
404                sb.append(", destroyed=").append(activity.isDestroyed());
405                sb.append(", startedActivity=").append(activity.mStartedActivity);
406                sb.append(", temporaryPause=").append(activity.mTemporaryPause);
407                sb.append(", changingConfigurations=").append(activity.mChangingConfigurations);
408                sb.append(", visibleBehind=").append(activity.mVisibleBehind);
409                sb.append("}");
410            }
411            sb.append("}");
412            return sb.toString();
413        }
414    }
415
416    final class ProviderClientRecord {
417        final String[] mNames;
418        final IContentProvider mProvider;
419        final ContentProvider mLocalProvider;
420        final IActivityManager.ContentProviderHolder mHolder;
421
422        ProviderClientRecord(String[] names, IContentProvider provider,
423                ContentProvider localProvider,
424                IActivityManager.ContentProviderHolder holder) {
425            mNames = names;
426            mProvider = provider;
427            mLocalProvider = localProvider;
428            mHolder = holder;
429        }
430    }
431
432    static final class NewIntentData {
433        List<ReferrerIntent> intents;
434        IBinder token;
435        public String toString() {
436            return "NewIntentData{intents=" + intents + " token=" + token + "}";
437        }
438    }
439
440    static final class ReceiverData extends BroadcastReceiver.PendingResult {
441        public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras,
442                boolean ordered, boolean sticky, IBinder token, int sendingUser) {
443            super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky,
444                    token, sendingUser, intent.getFlags());
445            this.intent = intent;
446        }
447
448        Intent intent;
449        ActivityInfo info;
450        CompatibilityInfo compatInfo;
451        public String toString() {
452            return "ReceiverData{intent=" + intent + " packageName=" +
453                    info.packageName + " resultCode=" + getResultCode()
454                    + " resultData=" + getResultData() + " resultExtras="
455                    + getResultExtras(false) + "}";
456        }
457    }
458
459    static final class CreateBackupAgentData {
460        ApplicationInfo appInfo;
461        CompatibilityInfo compatInfo;
462        int backupMode;
463        public String toString() {
464            return "CreateBackupAgentData{appInfo=" + appInfo
465                    + " backupAgent=" + appInfo.backupAgentName
466                    + " mode=" + backupMode + "}";
467        }
468    }
469
470    static final class CreateServiceData {
471        IBinder token;
472        ServiceInfo info;
473        CompatibilityInfo compatInfo;
474        Intent intent;
475        public String toString() {
476            return "CreateServiceData{token=" + token + " className="
477            + info.name + " packageName=" + info.packageName
478            + " intent=" + intent + "}";
479        }
480    }
481
482    static final class BindServiceData {
483        IBinder token;
484        Intent intent;
485        boolean rebind;
486        public String toString() {
487            return "BindServiceData{token=" + token + " intent=" + intent + "}";
488        }
489    }
490
491    static final class ServiceArgsData {
492        IBinder token;
493        boolean taskRemoved;
494        int startId;
495        int flags;
496        Intent args;
497        public String toString() {
498            return "ServiceArgsData{token=" + token + " startId=" + startId
499            + " args=" + args + "}";
500        }
501    }
502
503    static final class AppBindData {
504        LoadedApk info;
505        String processName;
506        ApplicationInfo appInfo;
507        List<ProviderInfo> providers;
508        ComponentName instrumentationName;
509        Bundle instrumentationArgs;
510        IInstrumentationWatcher instrumentationWatcher;
511        IUiAutomationConnection instrumentationUiAutomationConnection;
512        int debugMode;
513        boolean enableBinderTracking;
514        boolean trackAllocation;
515        boolean restrictedBackupMode;
516        boolean persistent;
517        Configuration config;
518        CompatibilityInfo compatInfo;
519
520        /** Initial values for {@link Profiler}. */
521        ProfilerInfo initProfilerInfo;
522
523        public String toString() {
524            return "AppBindData{appInfo=" + appInfo + "}";
525        }
526    }
527
528    static final class Profiler {
529        String profileFile;
530        ParcelFileDescriptor profileFd;
531        int samplingInterval;
532        boolean autoStopProfiler;
533        boolean profiling;
534        boolean handlingProfiling;
535        public void setProfiler(ProfilerInfo profilerInfo) {
536            ParcelFileDescriptor fd = profilerInfo.profileFd;
537            if (profiling) {
538                if (fd != null) {
539                    try {
540                        fd.close();
541                    } catch (IOException e) {
542                        // Ignore
543                    }
544                }
545                return;
546            }
547            if (profileFd != null) {
548                try {
549                    profileFd.close();
550                } catch (IOException e) {
551                    // Ignore
552                }
553            }
554            profileFile = profilerInfo.profileFile;
555            profileFd = fd;
556            samplingInterval = profilerInfo.samplingInterval;
557            autoStopProfiler = profilerInfo.autoStopProfiler;
558        }
559        public void startProfiling() {
560            if (profileFd == null || profiling) {
561                return;
562            }
563            try {
564                int bufferSize = SystemProperties.getInt("debug.traceview-buffer-size-mb", 8);
565                VMDebug.startMethodTracing(profileFile, profileFd.getFileDescriptor(),
566                        bufferSize * 1024 * 1024, 0, samplingInterval != 0, samplingInterval);
567                profiling = true;
568            } catch (RuntimeException e) {
569                Slog.w(TAG, "Profiling failed on path " + profileFile);
570                try {
571                    profileFd.close();
572                    profileFd = null;
573                } catch (IOException e2) {
574                    Slog.w(TAG, "Failure closing profile fd", e2);
575                }
576            }
577        }
578        public void stopProfiling() {
579            if (profiling) {
580                profiling = false;
581                Debug.stopMethodTracing();
582                if (profileFd != null) {
583                    try {
584                        profileFd.close();
585                    } catch (IOException e) {
586                    }
587                }
588                profileFd = null;
589                profileFile = null;
590            }
591        }
592    }
593
594    static final class DumpComponentInfo {
595        ParcelFileDescriptor fd;
596        IBinder token;
597        String prefix;
598        String[] args;
599    }
600
601    static final class ResultData {
602        IBinder token;
603        List<ResultInfo> results;
604        public String toString() {
605            return "ResultData{token=" + token + " results" + results + "}";
606        }
607    }
608
609    static final class ContextCleanupInfo {
610        ContextImpl context;
611        String what;
612        String who;
613    }
614
615    static final class DumpHeapData {
616        String path;
617        ParcelFileDescriptor fd;
618    }
619
620    static final class UpdateCompatibilityData {
621        String pkg;
622        CompatibilityInfo info;
623    }
624
625    static final class RequestAssistContextExtras {
626        IBinder activityToken;
627        IBinder requestToken;
628        int requestType;
629        int sessionId;
630    }
631
632    static final class ActivityConfigChangeData {
633        final IBinder activityToken;
634        final Configuration overrideConfig;
635        public ActivityConfigChangeData(IBinder token, Configuration config) {
636            activityToken = token;
637            overrideConfig = config;
638        }
639    }
640
641    private native void dumpGraphicsInfo(FileDescriptor fd);
642
643    private class ApplicationThread extends ApplicationThreadNative {
644        private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";
645
646        private int mLastProcessState = -1;
647
648        private void updatePendingConfiguration(Configuration config) {
649            synchronized (mResourcesManager) {
650                if (mPendingConfiguration == null ||
651                        mPendingConfiguration.isOtherSeqNewer(config)) {
652                    mPendingConfiguration = config;
653                }
654            }
655        }
656
657        public final void schedulePauseActivity(IBinder token, boolean finished,
658                boolean userLeaving, int configChanges, boolean dontReport) {
659            int seq = getLifecycleSeq();
660            if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this
661                    + " operation received seq: " + seq);
662            sendMessage(
663                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
664                    token,
665                    (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
666                    configChanges,
667                    seq);
668        }
669
670        public final void scheduleStopActivity(IBinder token, boolean showWindow,
671                int configChanges) {
672            int seq = getLifecycleSeq();
673            if (DEBUG_ORDER) Slog.d(TAG, "stopActivity " + ActivityThread.this
674                    + " operation received seq: " + seq);
675            sendMessage(
676                showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
677                token, 0, configChanges, seq);
678        }
679
680        public final void scheduleWindowVisibility(IBinder token, boolean showWindow) {
681            sendMessage(
682                showWindow ? H.SHOW_WINDOW : H.HIDE_WINDOW,
683                token);
684        }
685
686        public final void scheduleSleeping(IBinder token, boolean sleeping) {
687            sendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
688        }
689
690        public final void scheduleResumeActivity(IBinder token, int processState,
691                boolean isForward, Bundle resumeArgs) {
692            int seq = getLifecycleSeq();
693            if (DEBUG_ORDER) Slog.d(TAG, "resumeActivity " + ActivityThread.this
694                    + " operation received seq: " + seq);
695            updateProcessState(processState, false);
696            sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0, 0, seq);
697        }
698
699        public final void scheduleSendResult(IBinder token, List<ResultInfo> results) {
700            ResultData res = new ResultData();
701            res.token = token;
702            res.results = results;
703            sendMessage(H.SEND_RESULT, res);
704        }
705
706        // we use token to identify this activity without having to send the
707        // activity itself back to the activity manager. (matters more with ipc)
708        @Override
709        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
710                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
711                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
712                int procState, Bundle state, PersistableBundle persistentState,
713                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
714                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
715
716            updateProcessState(procState, false);
717
718            ActivityClientRecord r = new ActivityClientRecord();
719
720            r.token = token;
721            r.ident = ident;
722            r.intent = intent;
723            r.referrer = referrer;
724            r.voiceInteractor = voiceInteractor;
725            r.activityInfo = info;
726            r.compatInfo = compatInfo;
727            r.state = state;
728            r.persistentState = persistentState;
729
730            r.pendingResults = pendingResults;
731            r.pendingIntents = pendingNewIntents;
732
733            r.startsNotResumed = notResumed;
734            r.isForward = isForward;
735
736            r.profilerInfo = profilerInfo;
737
738            r.overrideConfig = overrideConfig;
739            updatePendingConfiguration(curConfig);
740
741            sendMessage(H.LAUNCH_ACTIVITY, r);
742        }
743
744        @Override
745        public final void scheduleRelaunchActivity(IBinder token,
746                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
747                int configChanges, boolean notResumed, Configuration config,
748                Configuration overrideConfig, boolean preserveWindow) {
749            requestRelaunchActivity(token, pendingResults, pendingNewIntents,
750                    configChanges, notResumed, config, overrideConfig, true, preserveWindow);
751        }
752
753        public final void scheduleNewIntent(List<ReferrerIntent> intents, IBinder token) {
754            NewIntentData data = new NewIntentData();
755            data.intents = intents;
756            data.token = token;
757
758            sendMessage(H.NEW_INTENT, data);
759        }
760
761        public final void scheduleDestroyActivity(IBinder token, boolean finishing,
762                int configChanges) {
763            sendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
764                    configChanges);
765        }
766
767        public final void scheduleReceiver(Intent intent, ActivityInfo info,
768                CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
769                boolean sync, int sendingUser, int processState) {
770            updateProcessState(processState, false);
771            ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
772                    sync, false, mAppThread.asBinder(), sendingUser);
773            r.info = info;
774            r.compatInfo = compatInfo;
775            sendMessage(H.RECEIVER, r);
776        }
777
778        public final void scheduleCreateBackupAgent(ApplicationInfo app,
779                CompatibilityInfo compatInfo, int backupMode) {
780            CreateBackupAgentData d = new CreateBackupAgentData();
781            d.appInfo = app;
782            d.compatInfo = compatInfo;
783            d.backupMode = backupMode;
784
785            sendMessage(H.CREATE_BACKUP_AGENT, d);
786        }
787
788        public final void scheduleDestroyBackupAgent(ApplicationInfo app,
789                CompatibilityInfo compatInfo) {
790            CreateBackupAgentData d = new CreateBackupAgentData();
791            d.appInfo = app;
792            d.compatInfo = compatInfo;
793
794            sendMessage(H.DESTROY_BACKUP_AGENT, d);
795        }
796
797        public final void scheduleCreateService(IBinder token,
798                ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
799            updateProcessState(processState, false);
800            CreateServiceData s = new CreateServiceData();
801            s.token = token;
802            s.info = info;
803            s.compatInfo = compatInfo;
804
805            sendMessage(H.CREATE_SERVICE, s);
806        }
807
808        public final void scheduleBindService(IBinder token, Intent intent,
809                boolean rebind, int processState) {
810            updateProcessState(processState, false);
811            BindServiceData s = new BindServiceData();
812            s.token = token;
813            s.intent = intent;
814            s.rebind = rebind;
815
816            if (DEBUG_SERVICE)
817                Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
818                        + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
819            sendMessage(H.BIND_SERVICE, s);
820        }
821
822        public final void scheduleUnbindService(IBinder token, Intent intent) {
823            BindServiceData s = new BindServiceData();
824            s.token = token;
825            s.intent = intent;
826
827            sendMessage(H.UNBIND_SERVICE, s);
828        }
829
830        public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
831            int flags ,Intent args) {
832            ServiceArgsData s = new ServiceArgsData();
833            s.token = token;
834            s.taskRemoved = taskRemoved;
835            s.startId = startId;
836            s.flags = flags;
837            s.args = args;
838
839            sendMessage(H.SERVICE_ARGS, s);
840        }
841
842        public final void scheduleStopService(IBinder token) {
843            sendMessage(H.STOP_SERVICE, token);
844        }
845
846        public final void bindApplication(String processName, ApplicationInfo appInfo,
847                List<ProviderInfo> providers, ComponentName instrumentationName,
848                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
849                IInstrumentationWatcher instrumentationWatcher,
850                IUiAutomationConnection instrumentationUiConnection, int debugMode,
851                boolean enableBinderTracking, boolean trackAllocation,
852                boolean isRestrictedBackupMode, boolean persistent, Configuration config,
853                CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {
854
855            if (services != null) {
856                // Setup the service cache in the ServiceManager
857                ServiceManager.initServiceCache(services);
858            }
859
860            setCoreSettings(coreSettings);
861
862            AppBindData data = new AppBindData();
863            data.processName = processName;
864            data.appInfo = appInfo;
865            data.providers = providers;
866            data.instrumentationName = instrumentationName;
867            data.instrumentationArgs = instrumentationArgs;
868            data.instrumentationWatcher = instrumentationWatcher;
869            data.instrumentationUiAutomationConnection = instrumentationUiConnection;
870            data.debugMode = debugMode;
871            data.enableBinderTracking = enableBinderTracking;
872            data.trackAllocation = trackAllocation;
873            data.restrictedBackupMode = isRestrictedBackupMode;
874            data.persistent = persistent;
875            data.config = config;
876            data.compatInfo = compatInfo;
877            data.initProfilerInfo = profilerInfo;
878            sendMessage(H.BIND_APPLICATION, data);
879        }
880
881        public final void scheduleExit() {
882            sendMessage(H.EXIT_APPLICATION, null);
883        }
884
885        public final void scheduleSuicide() {
886            sendMessage(H.SUICIDE, null);
887        }
888
889        public void scheduleConfigurationChanged(Configuration config) {
890            updatePendingConfiguration(config);
891            sendMessage(H.CONFIGURATION_CHANGED, config);
892        }
893
894        public void updateTimeZone() {
895            TimeZone.setDefault(null);
896        }
897
898        public void clearDnsCache() {
899            // a non-standard API to get this to libcore
900            InetAddress.clearDnsCache();
901            // Allow libcore to perform the necessary actions as it sees fit upon a network
902            // configuration change.
903            NetworkEventDispatcher.getInstance().onNetworkConfigurationChanged();
904        }
905
906        public void setHttpProxy(String host, String port, String exclList, Uri pacFileUrl) {
907            final ConnectivityManager cm = ConnectivityManager.from(getSystemContext());
908            final Network network = cm.getBoundNetworkForProcess();
909            if (network != null) {
910                Proxy.setHttpProxySystemProperty(cm.getDefaultProxy());
911            } else {
912                Proxy.setHttpProxySystemProperty(host, port, exclList, pacFileUrl);
913            }
914        }
915
916        public void processInBackground() {
917            mH.removeMessages(H.GC_WHEN_IDLE);
918            mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
919        }
920
921        public void dumpService(FileDescriptor fd, IBinder servicetoken, String[] args) {
922            DumpComponentInfo data = new DumpComponentInfo();
923            try {
924                data.fd = ParcelFileDescriptor.dup(fd);
925                data.token = servicetoken;
926                data.args = args;
927                sendMessage(H.DUMP_SERVICE, data, 0, 0, true /*async*/);
928            } catch (IOException e) {
929                Slog.w(TAG, "dumpService failed", e);
930            }
931        }
932
933        // This function exists to make sure all receiver dispatching is
934        // correctly ordered, since these are one-way calls and the binder driver
935        // applies transaction ordering per object for such calls.
936        public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
937                int resultCode, String dataStr, Bundle extras, boolean ordered,
938                boolean sticky, int sendingUser, int processState) throws RemoteException {
939            updateProcessState(processState, false);
940            receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
941                    sticky, sendingUser);
942        }
943
944        @Override
945        public void scheduleLowMemory() {
946            sendMessage(H.LOW_MEMORY, null);
947        }
948
949        @Override
950        public void scheduleActivityConfigurationChanged(
951                IBinder token, Configuration overrideConfig, boolean reportToActivity) {
952            sendMessage(H.ACTIVITY_CONFIGURATION_CHANGED,
953                    new ActivityConfigChangeData(token, overrideConfig), reportToActivity ? 1 : 0);
954        }
955
956        @Override
957        public void profilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) {
958            sendMessage(H.PROFILER_CONTROL, profilerInfo, start ? 1 : 0, profileType);
959        }
960
961        public void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd) {
962            DumpHeapData dhd = new DumpHeapData();
963            dhd.path = path;
964            dhd.fd = fd;
965            sendMessage(H.DUMP_HEAP, dhd, managed ? 1 : 0, 0, true /*async*/);
966        }
967
968        public void setSchedulingGroup(int group) {
969            // Note: do this immediately, since going into the foreground
970            // should happen regardless of what pending work we have to do
971            // and the activity manager will wait for us to report back that
972            // we are done before sending us to the background.
973            try {
974                Process.setProcessGroup(Process.myPid(), group);
975            } catch (Exception e) {
976                Slog.w(TAG, "Failed setting process group to " + group, e);
977            }
978        }
979
980        public void dispatchPackageBroadcast(int cmd, String[] packages) {
981            sendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
982        }
983
984        public void scheduleCrash(String msg) {
985            sendMessage(H.SCHEDULE_CRASH, msg);
986        }
987
988        public void dumpActivity(FileDescriptor fd, IBinder activitytoken,
989                String prefix, String[] args) {
990            DumpComponentInfo data = new DumpComponentInfo();
991            try {
992                data.fd = ParcelFileDescriptor.dup(fd);
993                data.token = activitytoken;
994                data.prefix = prefix;
995                data.args = args;
996                sendMessage(H.DUMP_ACTIVITY, data, 0, 0, true /*async*/);
997            } catch (IOException e) {
998                Slog.w(TAG, "dumpActivity failed", e);
999            }
1000        }
1001
1002        public void dumpProvider(FileDescriptor fd, IBinder providertoken,
1003                String[] args) {
1004            DumpComponentInfo data = new DumpComponentInfo();
1005            try {
1006                data.fd = ParcelFileDescriptor.dup(fd);
1007                data.token = providertoken;
1008                data.args = args;
1009                sendMessage(H.DUMP_PROVIDER, data, 0, 0, true /*async*/);
1010            } catch (IOException e) {
1011                Slog.w(TAG, "dumpProvider failed", e);
1012            }
1013        }
1014
1015        @Override
1016        public void dumpMemInfo(FileDescriptor fd, Debug.MemoryInfo mem, boolean checkin,
1017                boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
1018                boolean dumpUnreachable, String[] args) {
1019            FileOutputStream fout = new FileOutputStream(fd);
1020            PrintWriter pw = new FastPrintWriter(fout);
1021            try {
1022                dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly, dumpUnreachable);
1023            } finally {
1024                pw.flush();
1025            }
1026        }
1027
1028        private void dumpMemInfo(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
1029                boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable) {
1030            long nativeMax = Debug.getNativeHeapSize() / 1024;
1031            long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
1032            long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
1033
1034            Runtime runtime = Runtime.getRuntime();
1035            runtime.gc();  // Do GC since countInstancesOfClass counts unreachable objects.
1036            long dalvikMax = runtime.totalMemory() / 1024;
1037            long dalvikFree = runtime.freeMemory() / 1024;
1038            long dalvikAllocated = dalvikMax - dalvikFree;
1039            long viewInstanceCount = ViewDebug.getViewInstanceCount();
1040            long viewRootInstanceCount = ViewDebug.getViewRootImplCount();
1041            long appContextInstanceCount = Debug.countInstancesOfClass(ContextImpl.class);
1042            long activityInstanceCount = Debug.countInstancesOfClass(Activity.class);
1043            int globalAssetCount = AssetManager.getGlobalAssetCount();
1044            int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
1045            int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
1046            int binderProxyObjectCount = Debug.getBinderProxyObjectCount();
1047            int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
1048            long parcelSize = Parcel.getGlobalAllocSize();
1049            long parcelCount = Parcel.getGlobalAllocCount();
1050            long openSslSocketCount = Debug.countInstancesOfClass(OpenSSLSocketImpl.class);
1051            SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo();
1052
1053            dumpMemInfoTable(pw, memInfo, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly,
1054                    Process.myPid(),
1055                    (mBoundApplication != null) ? mBoundApplication.processName : "unknown",
1056                    nativeMax, nativeAllocated, nativeFree,
1057                    dalvikMax, dalvikAllocated, dalvikFree);
1058
1059            if (checkin) {
1060                // NOTE: if you change anything significant below, also consider changing
1061                // ACTIVITY_THREAD_CHECKIN_VERSION.
1062
1063                // Object counts
1064                pw.print(viewInstanceCount); pw.print(',');
1065                pw.print(viewRootInstanceCount); pw.print(',');
1066                pw.print(appContextInstanceCount); pw.print(',');
1067                pw.print(activityInstanceCount); pw.print(',');
1068
1069                pw.print(globalAssetCount); pw.print(',');
1070                pw.print(globalAssetManagerCount); pw.print(',');
1071                pw.print(binderLocalObjectCount); pw.print(',');
1072                pw.print(binderProxyObjectCount); pw.print(',');
1073
1074                pw.print(binderDeathObjectCount); pw.print(',');
1075                pw.print(openSslSocketCount); pw.print(',');
1076
1077                // SQL
1078                pw.print(stats.memoryUsed / 1024); pw.print(',');
1079                pw.print(stats.memoryUsed / 1024); pw.print(',');
1080                pw.print(stats.pageCacheOverflow / 1024); pw.print(',');
1081                pw.print(stats.largestMemAlloc / 1024);
1082                for (int i = 0; i < stats.dbStats.size(); i++) {
1083                    DbStats dbStats = stats.dbStats.get(i);
1084                    pw.print(','); pw.print(dbStats.dbName);
1085                    pw.print(','); pw.print(dbStats.pageSize);
1086                    pw.print(','); pw.print(dbStats.dbSize);
1087                    pw.print(','); pw.print(dbStats.lookaside);
1088                    pw.print(','); pw.print(dbStats.cache);
1089                    pw.print(','); pw.print(dbStats.cache);
1090                }
1091                pw.println();
1092
1093                return;
1094            }
1095
1096            pw.println(" ");
1097            pw.println(" Objects");
1098            printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRootImpl:",
1099                    viewRootInstanceCount);
1100
1101            printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount,
1102                    "Activities:", activityInstanceCount);
1103
1104            printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount,
1105                    "AssetManagers:", globalAssetManagerCount);
1106
1107            printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount,
1108                    "Proxy Binders:", binderProxyObjectCount);
1109            printRow(pw, TWO_COUNT_COLUMNS, "Parcel memory:", parcelSize/1024,
1110                    "Parcel count:", parcelCount);
1111            printRow(pw, TWO_COUNT_COLUMNS, "Death Recipients:", binderDeathObjectCount,
1112                    "OpenSSL Sockets:", openSslSocketCount);
1113
1114            // SQLite mem info
1115            pw.println(" ");
1116            pw.println(" SQL");
1117            printRow(pw, ONE_COUNT_COLUMN, "MEMORY_USED:", stats.memoryUsed / 1024);
1118            printRow(pw, TWO_COUNT_COLUMNS, "PAGECACHE_OVERFLOW:",
1119                    stats.pageCacheOverflow / 1024, "MALLOC_SIZE:", stats.largestMemAlloc / 1024);
1120            pw.println(" ");
1121            int N = stats.dbStats.size();
1122            if (N > 0) {
1123                pw.println(" DATABASES");
1124                printRow(pw, "  %8s %8s %14s %14s  %s", "pgsz", "dbsz", "Lookaside(b)", "cache",
1125                        "Dbname");
1126                for (int i = 0; i < N; i++) {
1127                    DbStats dbStats = stats.dbStats.get(i);
1128                    printRow(pw, DB_INFO_FORMAT,
1129                            (dbStats.pageSize > 0) ? String.valueOf(dbStats.pageSize) : " ",
1130                            (dbStats.dbSize > 0) ? String.valueOf(dbStats.dbSize) : " ",
1131                            (dbStats.lookaside > 0) ? String.valueOf(dbStats.lookaside) : " ",
1132                            dbStats.cache, dbStats.dbName);
1133                }
1134            }
1135
1136            // Asset details.
1137            String assetAlloc = AssetManager.getAssetAllocations();
1138            if (assetAlloc != null) {
1139                pw.println(" ");
1140                pw.println(" Asset Allocations");
1141                pw.print(assetAlloc);
1142            }
1143
1144            // Unreachable native memory
1145            if (dumpUnreachable) {
1146                boolean showContents = ((mBoundApplication != null)
1147                    && ((mBoundApplication.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0))
1148                    || android.os.Build.IS_DEBUGGABLE;
1149                pw.println(" ");
1150                pw.println(" Unreachable memory");
1151                pw.print(Debug.getUnreachableMemory(100, showContents));
1152            }
1153        }
1154
1155        @Override
1156        public void dumpGfxInfo(FileDescriptor fd, String[] args) {
1157            dumpGraphicsInfo(fd);
1158            WindowManagerGlobal.getInstance().dumpGfxInfo(fd, args);
1159        }
1160
1161        private void dumpDatabaseInfo(FileDescriptor fd, String[] args) {
1162            PrintWriter pw = new FastPrintWriter(new FileOutputStream(fd));
1163            PrintWriterPrinter printer = new PrintWriterPrinter(pw);
1164            SQLiteDebug.dump(printer, args);
1165            pw.flush();
1166        }
1167
1168        @Override
1169        public void dumpDbInfo(final FileDescriptor fd, final String[] args) {
1170            if (mSystemThread) {
1171                // Ensure this invocation is asynchronous to prevent writer waiting if buffer cannot
1172                // be consumed. But it must duplicate the file descriptor first, since caller might
1173                // be closing it.
1174                final ParcelFileDescriptor dup;
1175                try {
1176                    dup = ParcelFileDescriptor.dup(fd);
1177                } catch (IOException e) {
1178                    Log.w(TAG, "Could not dup FD " + fd.getInt$());
1179                    return;
1180                }
1181
1182                AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
1183                    @Override
1184                    public void run() {
1185                        try {
1186                            dumpDatabaseInfo(dup.getFileDescriptor(), args);
1187                        } finally {
1188                            IoUtils.closeQuietly(dup);
1189                        }
1190                    }
1191                });
1192            } else {
1193                dumpDatabaseInfo(fd, args);
1194            }
1195        }
1196
1197        @Override
1198        public void unstableProviderDied(IBinder provider) {
1199            sendMessage(H.UNSTABLE_PROVIDER_DIED, provider);
1200        }
1201
1202        @Override
1203        public void requestAssistContextExtras(IBinder activityToken, IBinder requestToken,
1204                int requestType, int sessionId) {
1205            RequestAssistContextExtras cmd = new RequestAssistContextExtras();
1206            cmd.activityToken = activityToken;
1207            cmd.requestToken = requestToken;
1208            cmd.requestType = requestType;
1209            cmd.sessionId = sessionId;
1210            sendMessage(H.REQUEST_ASSIST_CONTEXT_EXTRAS, cmd);
1211        }
1212
1213        public void setCoreSettings(Bundle coreSettings) {
1214            sendMessage(H.SET_CORE_SETTINGS, coreSettings);
1215        }
1216
1217        public void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) {
1218            UpdateCompatibilityData ucd = new UpdateCompatibilityData();
1219            ucd.pkg = pkg;
1220            ucd.info = info;
1221            sendMessage(H.UPDATE_PACKAGE_COMPATIBILITY_INFO, ucd);
1222        }
1223
1224        public void scheduleTrimMemory(int level) {
1225            sendMessage(H.TRIM_MEMORY, null, level);
1226        }
1227
1228        public void scheduleTranslucentConversionComplete(IBinder token, boolean drawComplete) {
1229            sendMessage(H.TRANSLUCENT_CONVERSION_COMPLETE, token, drawComplete ? 1 : 0);
1230        }
1231
1232        public void scheduleOnNewActivityOptions(IBinder token, ActivityOptions options) {
1233            sendMessage(H.ON_NEW_ACTIVITY_OPTIONS,
1234                    new Pair<IBinder, ActivityOptions>(token, options));
1235        }
1236
1237        public void setProcessState(int state) {
1238            updateProcessState(state, true);
1239        }
1240
1241        public void updateProcessState(int processState, boolean fromIpc) {
1242            synchronized (this) {
1243                if (mLastProcessState != processState) {
1244                    mLastProcessState = processState;
1245                    // Update Dalvik state based on ActivityManager.PROCESS_STATE_* constants.
1246                    final int DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE = 0;
1247                    final int DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE = 1;
1248                    int dalvikProcessState = DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE;
1249                    // TODO: Tune this since things like gmail sync are important background but not jank perceptible.
1250                    if (processState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
1251                        dalvikProcessState = DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE;
1252                    }
1253                    VMRuntime.getRuntime().updateProcessState(dalvikProcessState);
1254                    if (false) {
1255                        Slog.i(TAG, "******************* PROCESS STATE CHANGED TO: " + processState
1256                                + (fromIpc ? " (from ipc": ""));
1257                    }
1258                }
1259            }
1260        }
1261
1262        @Override
1263        public void scheduleInstallProvider(ProviderInfo provider) {
1264            sendMessage(H.INSTALL_PROVIDER, provider);
1265        }
1266
1267        @Override
1268        public final void updateTimePrefs(boolean is24Hour) {
1269            DateFormat.set24HourTimePref(is24Hour);
1270        }
1271
1272        @Override
1273        public void scheduleCancelVisibleBehind(IBinder token) {
1274            sendMessage(H.CANCEL_VISIBLE_BEHIND, token);
1275        }
1276
1277        @Override
1278        public void scheduleBackgroundVisibleBehindChanged(IBinder token, boolean visible) {
1279            sendMessage(H.BACKGROUND_VISIBLE_BEHIND_CHANGED, token, visible ? 1 : 0);
1280        }
1281
1282        @Override
1283        public void scheduleEnterAnimationComplete(IBinder token) {
1284            sendMessage(H.ENTER_ANIMATION_COMPLETE, token);
1285        }
1286
1287        @Override
1288        public void notifyCleartextNetwork(byte[] firstPacket) {
1289            if (StrictMode.vmCleartextNetworkEnabled()) {
1290                StrictMode.onCleartextNetworkDetected(firstPacket);
1291            }
1292        }
1293
1294        @Override
1295        public void startBinderTracking() {
1296            sendMessage(H.START_BINDER_TRACKING, null);
1297        }
1298
1299        @Override
1300        public void stopBinderTrackingAndDump(FileDescriptor fd) {
1301            try {
1302                sendMessage(H.STOP_BINDER_TRACKING_AND_DUMP, ParcelFileDescriptor.dup(fd));
1303            } catch (IOException e) {
1304            }
1305        }
1306
1307        @Override
1308        public void scheduleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode)
1309                throws RemoteException {
1310            sendMessage(H.MULTI_WINDOW_MODE_CHANGED, token, isInMultiWindowMode ? 1 : 0);
1311        }
1312
1313        @Override
1314        public void schedulePictureInPictureModeChanged(IBinder token, boolean isInPipMode)
1315                throws RemoteException {
1316            sendMessage(H.PICTURE_IN_PICTURE_MODE_CHANGED, token, isInPipMode ? 1 : 0);
1317        }
1318
1319        @Override
1320        public void scheduleLocalVoiceInteractionStarted(IBinder token,
1321                IVoiceInteractor voiceInteractor) throws RemoteException {
1322            SomeArgs args = SomeArgs.obtain();
1323            args.arg1 = token;
1324            args.arg2 = voiceInteractor;
1325            sendMessage(H.LOCAL_VOICE_INTERACTION_STARTED, args);
1326        }
1327    }
1328
1329    private int getLifecycleSeq() {
1330        synchronized (mResourcesManager) {
1331            return mLifecycleSeq++;
1332        }
1333    }
1334
1335    private class H extends Handler {
1336        public static final int LAUNCH_ACTIVITY         = 100;
1337        public static final int PAUSE_ACTIVITY          = 101;
1338        public static final int PAUSE_ACTIVITY_FINISHING= 102;
1339        public static final int STOP_ACTIVITY_SHOW      = 103;
1340        public static final int STOP_ACTIVITY_HIDE      = 104;
1341        public static final int SHOW_WINDOW             = 105;
1342        public static final int HIDE_WINDOW             = 106;
1343        public static final int RESUME_ACTIVITY         = 107;
1344        public static final int SEND_RESULT             = 108;
1345        public static final int DESTROY_ACTIVITY        = 109;
1346        public static final int BIND_APPLICATION        = 110;
1347        public static final int EXIT_APPLICATION        = 111;
1348        public static final int NEW_INTENT              = 112;
1349        public static final int RECEIVER                = 113;
1350        public static final int CREATE_SERVICE          = 114;
1351        public static final int SERVICE_ARGS            = 115;
1352        public static final int STOP_SERVICE            = 116;
1353
1354        public static final int CONFIGURATION_CHANGED   = 118;
1355        public static final int CLEAN_UP_CONTEXT        = 119;
1356        public static final int GC_WHEN_IDLE            = 120;
1357        public static final int BIND_SERVICE            = 121;
1358        public static final int UNBIND_SERVICE          = 122;
1359        public static final int DUMP_SERVICE            = 123;
1360        public static final int LOW_MEMORY              = 124;
1361        public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
1362        public static final int RELAUNCH_ACTIVITY       = 126;
1363        public static final int PROFILER_CONTROL        = 127;
1364        public static final int CREATE_BACKUP_AGENT     = 128;
1365        public static final int DESTROY_BACKUP_AGENT    = 129;
1366        public static final int SUICIDE                 = 130;
1367        public static final int REMOVE_PROVIDER         = 131;
1368        public static final int ENABLE_JIT              = 132;
1369        public static final int DISPATCH_PACKAGE_BROADCAST = 133;
1370        public static final int SCHEDULE_CRASH          = 134;
1371        public static final int DUMP_HEAP               = 135;
1372        public static final int DUMP_ACTIVITY           = 136;
1373        public static final int SLEEPING                = 137;
1374        public static final int SET_CORE_SETTINGS       = 138;
1375        public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
1376        public static final int TRIM_MEMORY             = 140;
1377        public static final int DUMP_PROVIDER           = 141;
1378        public static final int UNSTABLE_PROVIDER_DIED  = 142;
1379        public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143;
1380        public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144;
1381        public static final int INSTALL_PROVIDER        = 145;
1382        public static final int ON_NEW_ACTIVITY_OPTIONS = 146;
1383        public static final int CANCEL_VISIBLE_BEHIND = 147;
1384        public static final int BACKGROUND_VISIBLE_BEHIND_CHANGED = 148;
1385        public static final int ENTER_ANIMATION_COMPLETE = 149;
1386        public static final int START_BINDER_TRACKING = 150;
1387        public static final int STOP_BINDER_TRACKING_AND_DUMP = 151;
1388        public static final int MULTI_WINDOW_MODE_CHANGED = 152;
1389        public static final int PICTURE_IN_PICTURE_MODE_CHANGED = 153;
1390        public static final int LOCAL_VOICE_INTERACTION_STARTED = 154;
1391
1392        String codeToString(int code) {
1393            if (DEBUG_MESSAGES) {
1394                switch (code) {
1395                    case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
1396                    case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
1397                    case PAUSE_ACTIVITY_FINISHING: return "PAUSE_ACTIVITY_FINISHING";
1398                    case STOP_ACTIVITY_SHOW: return "STOP_ACTIVITY_SHOW";
1399                    case STOP_ACTIVITY_HIDE: return "STOP_ACTIVITY_HIDE";
1400                    case SHOW_WINDOW: return "SHOW_WINDOW";
1401                    case HIDE_WINDOW: return "HIDE_WINDOW";
1402                    case RESUME_ACTIVITY: return "RESUME_ACTIVITY";
1403                    case SEND_RESULT: return "SEND_RESULT";
1404                    case DESTROY_ACTIVITY: return "DESTROY_ACTIVITY";
1405                    case BIND_APPLICATION: return "BIND_APPLICATION";
1406                    case EXIT_APPLICATION: return "EXIT_APPLICATION";
1407                    case NEW_INTENT: return "NEW_INTENT";
1408                    case RECEIVER: return "RECEIVER";
1409                    case CREATE_SERVICE: return "CREATE_SERVICE";
1410                    case SERVICE_ARGS: return "SERVICE_ARGS";
1411                    case STOP_SERVICE: return "STOP_SERVICE";
1412                    case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
1413                    case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
1414                    case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
1415                    case BIND_SERVICE: return "BIND_SERVICE";
1416                    case UNBIND_SERVICE: return "UNBIND_SERVICE";
1417                    case DUMP_SERVICE: return "DUMP_SERVICE";
1418                    case LOW_MEMORY: return "LOW_MEMORY";
1419                    case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED";
1420                    case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
1421                    case PROFILER_CONTROL: return "PROFILER_CONTROL";
1422                    case CREATE_BACKUP_AGENT: return "CREATE_BACKUP_AGENT";
1423                    case DESTROY_BACKUP_AGENT: return "DESTROY_BACKUP_AGENT";
1424                    case SUICIDE: return "SUICIDE";
1425                    case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
1426                    case ENABLE_JIT: return "ENABLE_JIT";
1427                    case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
1428                    case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
1429                    case DUMP_HEAP: return "DUMP_HEAP";
1430                    case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
1431                    case SLEEPING: return "SLEEPING";
1432                    case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS";
1433                    case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO";
1434                    case TRIM_MEMORY: return "TRIM_MEMORY";
1435                    case DUMP_PROVIDER: return "DUMP_PROVIDER";
1436                    case UNSTABLE_PROVIDER_DIED: return "UNSTABLE_PROVIDER_DIED";
1437                    case REQUEST_ASSIST_CONTEXT_EXTRAS: return "REQUEST_ASSIST_CONTEXT_EXTRAS";
1438                    case TRANSLUCENT_CONVERSION_COMPLETE: return "TRANSLUCENT_CONVERSION_COMPLETE";
1439                    case INSTALL_PROVIDER: return "INSTALL_PROVIDER";
1440                    case ON_NEW_ACTIVITY_OPTIONS: return "ON_NEW_ACTIVITY_OPTIONS";
1441                    case CANCEL_VISIBLE_BEHIND: return "CANCEL_VISIBLE_BEHIND";
1442                    case BACKGROUND_VISIBLE_BEHIND_CHANGED: return "BACKGROUND_VISIBLE_BEHIND_CHANGED";
1443                    case ENTER_ANIMATION_COMPLETE: return "ENTER_ANIMATION_COMPLETE";
1444                    case MULTI_WINDOW_MODE_CHANGED: return "MULTI_WINDOW_MODE_CHANGED";
1445                    case PICTURE_IN_PICTURE_MODE_CHANGED: return "PICTURE_IN_PICTURE_MODE_CHANGED";
1446                    case LOCAL_VOICE_INTERACTION_STARTED: return "LOCAL_VOICE_INTERACTION_STARTED";
1447                }
1448            }
1449            return Integer.toString(code);
1450        }
1451        public void handleMessage(Message msg) {
1452            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
1453            switch (msg.what) {
1454                case LAUNCH_ACTIVITY: {
1455                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
1456                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
1457
1458                    r.packageInfo = getPackageInfoNoCheck(
1459                            r.activityInfo.applicationInfo, r.compatInfo);
1460                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
1461                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1462                } break;
1463                case RELAUNCH_ACTIVITY: {
1464                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
1465                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
1466                    handleRelaunchActivity(r);
1467                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1468                } break;
1469                case PAUSE_ACTIVITY: {
1470                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
1471                    SomeArgs args = (SomeArgs) msg.obj;
1472                    handlePauseActivity((IBinder) args.arg1, false,
1473                            (args.argi1 & USER_LEAVING) != 0, args.argi2,
1474                            (args.argi1 & DONT_REPORT) != 0, args.argi3);
1475                    maybeSnapshot();
1476                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1477                } break;
1478                case PAUSE_ACTIVITY_FINISHING: {
1479                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
1480                    SomeArgs args = (SomeArgs) msg.obj;
1481                    handlePauseActivity((IBinder) args.arg1, true, (args.argi1 & USER_LEAVING) != 0,
1482                            args.argi2, (args.argi1 & DONT_REPORT) != 0, args.argi3);
1483                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1484                } break;
1485                case STOP_ACTIVITY_SHOW: {
1486                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
1487                    SomeArgs args = (SomeArgs) msg.obj;
1488                    handleStopActivity((IBinder) args.arg1, true, args.argi2, args.argi3);
1489                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1490                } break;
1491                case STOP_ACTIVITY_HIDE: {
1492                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
1493                    SomeArgs args = (SomeArgs) msg.obj;
1494                    handleStopActivity((IBinder) args.arg1, false, args.argi2, args.argi3);
1495                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1496                } break;
1497                case SHOW_WINDOW:
1498                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityShowWindow");
1499                    handleWindowVisibility((IBinder)msg.obj, true);
1500                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1501                    break;
1502                case HIDE_WINDOW:
1503                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityHideWindow");
1504                    handleWindowVisibility((IBinder)msg.obj, false);
1505                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1506                    break;
1507                case RESUME_ACTIVITY:
1508                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
1509                    SomeArgs args = (SomeArgs) msg.obj;
1510                    handleResumeActivity((IBinder) args.arg1, true, args.argi1 != 0, true,
1511                            args.argi3, "RESUME_ACTIVITY");
1512                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1513                    break;
1514                case SEND_RESULT:
1515                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult");
1516                    handleSendResult((ResultData)msg.obj);
1517                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1518                    break;
1519                case DESTROY_ACTIVITY:
1520                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
1521                    handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
1522                            msg.arg2, false);
1523                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1524                    break;
1525                case BIND_APPLICATION:
1526                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
1527                    AppBindData data = (AppBindData)msg.obj;
1528                    handleBindApplication(data);
1529                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1530                    break;
1531                case EXIT_APPLICATION:
1532                    if (mInitialApplication != null) {
1533                        mInitialApplication.onTerminate();
1534                    }
1535                    Looper.myLooper().quit();
1536                    break;
1537                case NEW_INTENT:
1538                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent");
1539                    handleNewIntent((NewIntentData)msg.obj);
1540                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1541                    break;
1542                case RECEIVER:
1543                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
1544                    handleReceiver((ReceiverData)msg.obj);
1545                    maybeSnapshot();
1546                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1547                    break;
1548                case CREATE_SERVICE:
1549                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
1550                    handleCreateService((CreateServiceData)msg.obj);
1551                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1552                    break;
1553                case BIND_SERVICE:
1554                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
1555                    handleBindService((BindServiceData)msg.obj);
1556                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1557                    break;
1558                case UNBIND_SERVICE:
1559                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
1560                    handleUnbindService((BindServiceData)msg.obj);
1561                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1562                    break;
1563                case SERVICE_ARGS:
1564                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceStart: " + String.valueOf(msg.obj)));
1565                    handleServiceArgs((ServiceArgsData)msg.obj);
1566                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1567                    break;
1568                case STOP_SERVICE:
1569                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
1570                    handleStopService((IBinder)msg.obj);
1571                    maybeSnapshot();
1572                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1573                    break;
1574                case CONFIGURATION_CHANGED:
1575                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
1576                    mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;
1577                    handleConfigurationChanged((Configuration)msg.obj, null);
1578                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1579                    break;
1580                case CLEAN_UP_CONTEXT:
1581                    ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
1582                    cci.context.performFinalCleanup(cci.who, cci.what);
1583                    break;
1584                case GC_WHEN_IDLE:
1585                    scheduleGcIdler();
1586                    break;
1587                case DUMP_SERVICE:
1588                    handleDumpService((DumpComponentInfo)msg.obj);
1589                    break;
1590                case LOW_MEMORY:
1591                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "lowMemory");
1592                    handleLowMemory();
1593                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1594                    break;
1595                case ACTIVITY_CONFIGURATION_CHANGED:
1596                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityConfigChanged");
1597                    handleActivityConfigurationChanged((ActivityConfigChangeData) msg.obj,
1598                            msg.arg1 == 1 ? REPORT_TO_ACTIVITY : !REPORT_TO_ACTIVITY);
1599                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1600                    break;
1601                case PROFILER_CONTROL:
1602                    handleProfilerControl(msg.arg1 != 0, (ProfilerInfo)msg.obj, msg.arg2);
1603                    break;
1604                case CREATE_BACKUP_AGENT:
1605                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupCreateAgent");
1606                    handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
1607                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1608                    break;
1609                case DESTROY_BACKUP_AGENT:
1610                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupDestroyAgent");
1611                    handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
1612                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1613                    break;
1614                case SUICIDE:
1615                    Process.killProcess(Process.myPid());
1616                    break;
1617                case REMOVE_PROVIDER:
1618                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "providerRemove");
1619                    completeRemoveProvider((ProviderRefCount)msg.obj);
1620                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1621                    break;
1622                case ENABLE_JIT:
1623                    ensureJitEnabled();
1624                    break;
1625                case DISPATCH_PACKAGE_BROADCAST:
1626                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastPackage");
1627                    handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
1628                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1629                    break;
1630                case SCHEDULE_CRASH:
1631                    throw new RemoteServiceException((String)msg.obj);
1632                case DUMP_HEAP:
1633                    handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj);
1634                    break;
1635                case DUMP_ACTIVITY:
1636                    handleDumpActivity((DumpComponentInfo)msg.obj);
1637                    break;
1638                case DUMP_PROVIDER:
1639                    handleDumpProvider((DumpComponentInfo)msg.obj);
1640                    break;
1641                case SLEEPING:
1642                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "sleeping");
1643                    handleSleeping((IBinder)msg.obj, msg.arg1 != 0);
1644                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1645                    break;
1646                case SET_CORE_SETTINGS:
1647                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setCoreSettings");
1648                    handleSetCoreSettings((Bundle) msg.obj);
1649                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1650                    break;
1651                case UPDATE_PACKAGE_COMPATIBILITY_INFO:
1652                    handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj);
1653                    break;
1654                case TRIM_MEMORY:
1655                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "trimMemory");
1656                    handleTrimMemory(msg.arg1);
1657                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1658                    break;
1659                case UNSTABLE_PROVIDER_DIED:
1660                    handleUnstableProviderDied((IBinder)msg.obj, false);
1661                    break;
1662                case REQUEST_ASSIST_CONTEXT_EXTRAS:
1663                    handleRequestAssistContextExtras((RequestAssistContextExtras)msg.obj);
1664                    break;
1665                case TRANSLUCENT_CONVERSION_COMPLETE:
1666                    handleTranslucentConversionComplete((IBinder)msg.obj, msg.arg1 == 1);
1667                    break;
1668                case INSTALL_PROVIDER:
1669                    handleInstallProvider((ProviderInfo) msg.obj);
1670                    break;
1671                case ON_NEW_ACTIVITY_OPTIONS:
1672                    Pair<IBinder, ActivityOptions> pair = (Pair<IBinder, ActivityOptions>) msg.obj;
1673                    onNewActivityOptions(pair.first, pair.second);
1674                    break;
1675                case CANCEL_VISIBLE_BEHIND:
1676                    handleCancelVisibleBehind((IBinder) msg.obj);
1677                    break;
1678                case BACKGROUND_VISIBLE_BEHIND_CHANGED:
1679                    handleOnBackgroundVisibleBehindChanged((IBinder) msg.obj, msg.arg1 > 0);
1680                    break;
1681                case ENTER_ANIMATION_COMPLETE:
1682                    handleEnterAnimationComplete((IBinder) msg.obj);
1683                    break;
1684                case START_BINDER_TRACKING:
1685                    handleStartBinderTracking();
1686                    break;
1687                case STOP_BINDER_TRACKING_AND_DUMP:
1688                    handleStopBinderTrackingAndDump((ParcelFileDescriptor) msg.obj);
1689                    break;
1690                case MULTI_WINDOW_MODE_CHANGED:
1691                    handleMultiWindowModeChanged((IBinder) msg.obj, msg.arg1 == 1);
1692                    break;
1693                case PICTURE_IN_PICTURE_MODE_CHANGED:
1694                    handlePictureInPictureModeChanged((IBinder) msg.obj, msg.arg1 == 1);
1695                    break;
1696                case LOCAL_VOICE_INTERACTION_STARTED:
1697                    handleLocalVoiceInteractionStarted((IBinder) ((SomeArgs) msg.obj).arg1,
1698                            (IVoiceInteractor) ((SomeArgs) msg.obj).arg2);
1699                    break;
1700            }
1701            Object obj = msg.obj;
1702            if (obj instanceof SomeArgs) {
1703                ((SomeArgs) obj).recycle();
1704            }
1705            if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
1706        }
1707
1708        private void maybeSnapshot() {
1709            if (mBoundApplication != null && SamplingProfilerIntegration.isEnabled()) {
1710                // convert the *private* ActivityThread.PackageInfo to *public* known
1711                // android.content.pm.PackageInfo
1712                String packageName = mBoundApplication.info.mPackageName;
1713                android.content.pm.PackageInfo packageInfo = null;
1714                try {
1715                    Context context = getSystemContext();
1716                    if(context == null) {
1717                        Log.e(TAG, "cannot get a valid context");
1718                        return;
1719                    }
1720                    PackageManager pm = context.getPackageManager();
1721                    if(pm == null) {
1722                        Log.e(TAG, "cannot get a valid PackageManager");
1723                        return;
1724                    }
1725                    packageInfo = pm.getPackageInfo(
1726                            packageName, PackageManager.GET_ACTIVITIES);
1727                } catch (NameNotFoundException e) {
1728                    Log.e(TAG, "cannot get package info for " + packageName, e);
1729                }
1730                SamplingProfilerIntegration.writeSnapshot(mBoundApplication.processName, packageInfo);
1731            }
1732        }
1733    }
1734
1735    private class Idler implements MessageQueue.IdleHandler {
1736        @Override
1737        public final boolean queueIdle() {
1738            ActivityClientRecord a = mNewActivities;
1739            boolean stopProfiling = false;
1740            if (mBoundApplication != null && mProfiler.profileFd != null
1741                    && mProfiler.autoStopProfiler) {
1742                stopProfiling = true;
1743            }
1744            if (a != null) {
1745                mNewActivities = null;
1746                IActivityManager am = ActivityManagerNative.getDefault();
1747                ActivityClientRecord prev;
1748                do {
1749                    if (localLOGV) Slog.v(
1750                        TAG, "Reporting idle of " + a +
1751                        " finished=" +
1752                        (a.activity != null && a.activity.mFinished));
1753                    if (a.activity != null && !a.activity.mFinished) {
1754                        try {
1755                            am.activityIdle(a.token, a.createdConfig, stopProfiling);
1756                            a.createdConfig = null;
1757                        } catch (RemoteException ex) {
1758                            throw ex.rethrowFromSystemServer();
1759                        }
1760                    }
1761                    prev = a;
1762                    a = a.nextIdle;
1763                    prev.nextIdle = null;
1764                } while (a != null);
1765            }
1766            if (stopProfiling) {
1767                mProfiler.stopProfiling();
1768            }
1769            ensureJitEnabled();
1770            return false;
1771        }
1772    }
1773
1774    final class GcIdler implements MessageQueue.IdleHandler {
1775        @Override
1776        public final boolean queueIdle() {
1777            doGcIfNeeded();
1778            return false;
1779        }
1780    }
1781
1782    public static ActivityThread currentActivityThread() {
1783        return sCurrentActivityThread;
1784    }
1785
1786    public static boolean isSystem() {
1787        return (sCurrentActivityThread != null) ? sCurrentActivityThread.mSystemThread : false;
1788    }
1789
1790    public static String currentOpPackageName() {
1791        ActivityThread am = currentActivityThread();
1792        return (am != null && am.getApplication() != null)
1793                ? am.getApplication().getOpPackageName() : null;
1794    }
1795
1796    public static String currentPackageName() {
1797        ActivityThread am = currentActivityThread();
1798        return (am != null && am.mBoundApplication != null)
1799            ? am.mBoundApplication.appInfo.packageName : null;
1800    }
1801
1802    public static String currentProcessName() {
1803        ActivityThread am = currentActivityThread();
1804        return (am != null && am.mBoundApplication != null)
1805            ? am.mBoundApplication.processName : null;
1806    }
1807
1808    public static Application currentApplication() {
1809        ActivityThread am = currentActivityThread();
1810        return am != null ? am.mInitialApplication : null;
1811    }
1812
1813    public static IPackageManager getPackageManager() {
1814        if (sPackageManager != null) {
1815            //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
1816            return sPackageManager;
1817        }
1818        IBinder b = ServiceManager.getService("package");
1819        //Slog.v("PackageManager", "default service binder = " + b);
1820        sPackageManager = IPackageManager.Stub.asInterface(b);
1821        //Slog.v("PackageManager", "default service = " + sPackageManager);
1822        return sPackageManager;
1823    }
1824
1825    private Configuration mMainThreadConfig = new Configuration();
1826
1827    Configuration applyConfigCompatMainThread(int displayDensity, Configuration config,
1828            CompatibilityInfo compat) {
1829        if (config == null) {
1830            return null;
1831        }
1832        if (!compat.supportsScreen()) {
1833            mMainThreadConfig.setTo(config);
1834            config = mMainThreadConfig;
1835            compat.applyToConfiguration(displayDensity, config);
1836        }
1837        return config;
1838    }
1839
1840    /**
1841     * Creates the top level resources for the given package. Will return an existing
1842     * Resources if one has already been created.
1843     */
1844    Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
1845            String[] libDirs, int displayId, LoadedApk pkgInfo) {
1846        return mResourcesManager.getResources(null, resDir, splitResDirs, overlayDirs, libDirs,
1847                displayId, null, pkgInfo.getCompatibilityInfo(), pkgInfo.getClassLoader());
1848    }
1849
1850    final Handler getHandler() {
1851        return mH;
1852    }
1853
1854    public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
1855            int flags) {
1856        return getPackageInfo(packageName, compatInfo, flags, UserHandle.myUserId());
1857    }
1858
1859    public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
1860            int flags, int userId) {
1861        final boolean differentUser = (UserHandle.myUserId() != userId);
1862        synchronized (mResourcesManager) {
1863            WeakReference<LoadedApk> ref;
1864            if (differentUser) {
1865                // Caching not supported across users
1866                ref = null;
1867            } else if ((flags & Context.CONTEXT_INCLUDE_CODE) != 0) {
1868                ref = mPackages.get(packageName);
1869            } else {
1870                ref = mResourcePackages.get(packageName);
1871            }
1872
1873            LoadedApk packageInfo = ref != null ? ref.get() : null;
1874            //Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo);
1875            //if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir
1876            //        + ": " + packageInfo.mResources.getAssets().isUpToDate());
1877            if (packageInfo != null && (packageInfo.mResources == null
1878                    || packageInfo.mResources.getAssets().isUpToDate())) {
1879                if (packageInfo.isSecurityViolation()
1880                        && (flags&Context.CONTEXT_IGNORE_SECURITY) == 0) {
1881                    throw new SecurityException(
1882                            "Requesting code from " + packageName
1883                            + " to be run in process "
1884                            + mBoundApplication.processName
1885                            + "/" + mBoundApplication.appInfo.uid);
1886                }
1887                return packageInfo;
1888            }
1889        }
1890
1891        ApplicationInfo ai = null;
1892        try {
1893            ai = getPackageManager().getApplicationInfo(packageName,
1894                    PackageManager.GET_SHARED_LIBRARY_FILES
1895                            | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
1896                    userId);
1897        } catch (RemoteException e) {
1898            throw e.rethrowFromSystemServer();
1899        }
1900
1901        if (ai != null) {
1902            return getPackageInfo(ai, compatInfo, flags);
1903        }
1904
1905        return null;
1906    }
1907
1908    public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo,
1909            int flags) {
1910        boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
1911        boolean securityViolation = includeCode && ai.uid != 0
1912                && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
1913                        ? !UserHandle.isSameApp(ai.uid, mBoundApplication.appInfo.uid)
1914                        : true);
1915        boolean registerPackage = includeCode && (flags&Context.CONTEXT_REGISTER_PACKAGE) != 0;
1916        if ((flags&(Context.CONTEXT_INCLUDE_CODE
1917                |Context.CONTEXT_IGNORE_SECURITY))
1918                == Context.CONTEXT_INCLUDE_CODE) {
1919            if (securityViolation) {
1920                String msg = "Requesting code from " + ai.packageName
1921                        + " (with uid " + ai.uid + ")";
1922                if (mBoundApplication != null) {
1923                    msg = msg + " to be run in process "
1924                        + mBoundApplication.processName + " (with uid "
1925                        + mBoundApplication.appInfo.uid + ")";
1926                }
1927                throw new SecurityException(msg);
1928            }
1929        }
1930        return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode,
1931                registerPackage);
1932    }
1933
1934    public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
1935            CompatibilityInfo compatInfo) {
1936        return getPackageInfo(ai, compatInfo, null, false, true, false);
1937    }
1938
1939    public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) {
1940        synchronized (mResourcesManager) {
1941            WeakReference<LoadedApk> ref;
1942            if (includeCode) {
1943                ref = mPackages.get(packageName);
1944            } else {
1945                ref = mResourcePackages.get(packageName);
1946            }
1947            return ref != null ? ref.get() : null;
1948        }
1949    }
1950
1951    private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
1952            ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
1953            boolean registerPackage) {
1954        final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
1955        synchronized (mResourcesManager) {
1956            WeakReference<LoadedApk> ref;
1957            if (differentUser) {
1958                // Caching not supported across users
1959                ref = null;
1960            } else if (includeCode) {
1961                ref = mPackages.get(aInfo.packageName);
1962            } else {
1963                ref = mResourcePackages.get(aInfo.packageName);
1964            }
1965
1966            LoadedApk packageInfo = ref != null ? ref.get() : null;
1967            if (packageInfo == null || (packageInfo.mResources != null
1968                    && !packageInfo.mResources.getAssets().isUpToDate())) {
1969                if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package "
1970                        : "Loading resource-only package ") + aInfo.packageName
1971                        + " (in " + (mBoundApplication != null
1972                                ? mBoundApplication.processName : null)
1973                        + ")");
1974                packageInfo =
1975                    new LoadedApk(this, aInfo, compatInfo, baseLoader,
1976                            securityViolation, includeCode &&
1977                            (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
1978
1979                if (mSystemThread && "android".equals(aInfo.packageName)) {
1980                    packageInfo.installSystemApplicationInfo(aInfo,
1981                            getSystemContext().mPackageInfo.getClassLoader());
1982                }
1983
1984                if (differentUser) {
1985                    // Caching not supported across users
1986                } else if (includeCode) {
1987                    mPackages.put(aInfo.packageName,
1988                            new WeakReference<LoadedApk>(packageInfo));
1989                } else {
1990                    mResourcePackages.put(aInfo.packageName,
1991                            new WeakReference<LoadedApk>(packageInfo));
1992                }
1993            }
1994            return packageInfo;
1995        }
1996    }
1997
1998    ActivityThread() {
1999        mResourcesManager = ResourcesManager.getInstance();
2000    }
2001
2002    public ApplicationThread getApplicationThread()
2003    {
2004        return mAppThread;
2005    }
2006
2007    public Instrumentation getInstrumentation()
2008    {
2009        return mInstrumentation;
2010    }
2011
2012    public boolean isProfiling() {
2013        return mProfiler != null && mProfiler.profileFile != null
2014                && mProfiler.profileFd == null;
2015    }
2016
2017    public String getProfileFilePath() {
2018        return mProfiler.profileFile;
2019    }
2020
2021    public Looper getLooper() {
2022        return mLooper;
2023    }
2024
2025    public Application getApplication() {
2026        return mInitialApplication;
2027    }
2028
2029    public String getProcessName() {
2030        return mBoundApplication.processName;
2031    }
2032
2033    public ContextImpl getSystemContext() {
2034        synchronized (this) {
2035            if (mSystemContext == null) {
2036                mSystemContext = ContextImpl.createSystemContext(this);
2037            }
2038            return mSystemContext;
2039        }
2040    }
2041
2042    public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
2043        synchronized (this) {
2044            getSystemContext().installSystemApplicationInfo(info, classLoader);
2045
2046            // give ourselves a default profiler
2047            mProfiler = new Profiler();
2048        }
2049    }
2050
2051    void ensureJitEnabled() {
2052        if (!mJitEnabled) {
2053            mJitEnabled = true;
2054            dalvik.system.VMRuntime.getRuntime().startJitCompilation();
2055        }
2056    }
2057
2058    void scheduleGcIdler() {
2059        if (!mGcIdlerScheduled) {
2060            mGcIdlerScheduled = true;
2061            Looper.myQueue().addIdleHandler(mGcIdler);
2062        }
2063        mH.removeMessages(H.GC_WHEN_IDLE);
2064    }
2065
2066    void unscheduleGcIdler() {
2067        if (mGcIdlerScheduled) {
2068            mGcIdlerScheduled = false;
2069            Looper.myQueue().removeIdleHandler(mGcIdler);
2070        }
2071        mH.removeMessages(H.GC_WHEN_IDLE);
2072    }
2073
2074    void doGcIfNeeded() {
2075        mGcIdlerScheduled = false;
2076        final long now = SystemClock.uptimeMillis();
2077        //Slog.i(TAG, "**** WE MIGHT WANT TO GC: then=" + Binder.getLastGcTime()
2078        //        + "m now=" + now);
2079        if ((BinderInternal.getLastGcTime()+MIN_TIME_BETWEEN_GCS) < now) {
2080            //Slog.i(TAG, "**** WE DO, WE DO WANT TO GC!");
2081            BinderInternal.forceGc("bg");
2082        }
2083    }
2084
2085    private static final String HEAP_FULL_COLUMN
2086            = "%13s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s";
2087    private static final String HEAP_COLUMN
2088            = "%13s %8s %8s %8s %8s %8s %8s %8s";
2089    private static final String ONE_COUNT_COLUMN = "%21s %8d";
2090    private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d";
2091    private static final String ONE_COUNT_COLUMN_HEADER = "%21s %8s";
2092
2093    // Formatting for checkin service - update version if row format changes
2094    private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 4;
2095
2096    static void printRow(PrintWriter pw, String format, Object...objs) {
2097        pw.println(String.format(format, objs));
2098    }
2099
2100    public static void dumpMemInfoTable(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
2101            boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
2102            int pid, String processName,
2103            long nativeMax, long nativeAllocated, long nativeFree,
2104            long dalvikMax, long dalvikAllocated, long dalvikFree) {
2105
2106        // For checkin, we print one long comma-separated list of values
2107        if (checkin) {
2108            // NOTE: if you change anything significant below, also consider changing
2109            // ACTIVITY_THREAD_CHECKIN_VERSION.
2110
2111            // Header
2112            pw.print(ACTIVITY_THREAD_CHECKIN_VERSION); pw.print(',');
2113            pw.print(pid); pw.print(',');
2114            pw.print(processName); pw.print(',');
2115
2116            // Heap info - max
2117            pw.print(nativeMax); pw.print(',');
2118            pw.print(dalvikMax); pw.print(',');
2119            pw.print("N/A,");
2120            pw.print(nativeMax + dalvikMax); pw.print(',');
2121
2122            // Heap info - allocated
2123            pw.print(nativeAllocated); pw.print(',');
2124            pw.print(dalvikAllocated); pw.print(',');
2125            pw.print("N/A,");
2126            pw.print(nativeAllocated + dalvikAllocated); pw.print(',');
2127
2128            // Heap info - free
2129            pw.print(nativeFree); pw.print(',');
2130            pw.print(dalvikFree); pw.print(',');
2131            pw.print("N/A,");
2132            pw.print(nativeFree + dalvikFree); pw.print(',');
2133
2134            // Heap info - proportional set size
2135            pw.print(memInfo.nativePss); pw.print(',');
2136            pw.print(memInfo.dalvikPss); pw.print(',');
2137            pw.print(memInfo.otherPss); pw.print(',');
2138            pw.print(memInfo.getTotalPss()); pw.print(',');
2139
2140            // Heap info - swappable set size
2141            pw.print(memInfo.nativeSwappablePss); pw.print(',');
2142            pw.print(memInfo.dalvikSwappablePss); pw.print(',');
2143            pw.print(memInfo.otherSwappablePss); pw.print(',');
2144            pw.print(memInfo.getTotalSwappablePss()); pw.print(',');
2145
2146            // Heap info - shared dirty
2147            pw.print(memInfo.nativeSharedDirty); pw.print(',');
2148            pw.print(memInfo.dalvikSharedDirty); pw.print(',');
2149            pw.print(memInfo.otherSharedDirty); pw.print(',');
2150            pw.print(memInfo.getTotalSharedDirty()); pw.print(',');
2151
2152            // Heap info - shared clean
2153            pw.print(memInfo.nativeSharedClean); pw.print(',');
2154            pw.print(memInfo.dalvikSharedClean); pw.print(',');
2155            pw.print(memInfo.otherSharedClean); pw.print(',');
2156            pw.print(memInfo.getTotalSharedClean()); pw.print(',');
2157
2158            // Heap info - private Dirty
2159            pw.print(memInfo.nativePrivateDirty); pw.print(',');
2160            pw.print(memInfo.dalvikPrivateDirty); pw.print(',');
2161            pw.print(memInfo.otherPrivateDirty); pw.print(',');
2162            pw.print(memInfo.getTotalPrivateDirty()); pw.print(',');
2163
2164            // Heap info - private Clean
2165            pw.print(memInfo.nativePrivateClean); pw.print(',');
2166            pw.print(memInfo.dalvikPrivateClean); pw.print(',');
2167            pw.print(memInfo.otherPrivateClean); pw.print(',');
2168            pw.print(memInfo.getTotalPrivateClean()); pw.print(',');
2169
2170            // Heap info - swapped out
2171            pw.print(memInfo.nativeSwappedOut); pw.print(',');
2172            pw.print(memInfo.dalvikSwappedOut); pw.print(',');
2173            pw.print(memInfo.otherSwappedOut); pw.print(',');
2174            pw.print(memInfo.getTotalSwappedOut()); pw.print(',');
2175
2176            // Heap info - swapped out pss
2177            if (memInfo.hasSwappedOutPss) {
2178                pw.print(memInfo.nativeSwappedOutPss); pw.print(',');
2179                pw.print(memInfo.dalvikSwappedOutPss); pw.print(',');
2180                pw.print(memInfo.otherSwappedOutPss); pw.print(',');
2181                pw.print(memInfo.getTotalSwappedOutPss()); pw.print(',');
2182            } else {
2183                pw.print("N/A,");
2184                pw.print("N/A,");
2185                pw.print("N/A,");
2186                pw.print("N/A,");
2187            }
2188
2189            // Heap info - other areas
2190            for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
2191                pw.print(Debug.MemoryInfo.getOtherLabel(i)); pw.print(',');
2192                pw.print(memInfo.getOtherPss(i)); pw.print(',');
2193                pw.print(memInfo.getOtherSwappablePss(i)); pw.print(',');
2194                pw.print(memInfo.getOtherSharedDirty(i)); pw.print(',');
2195                pw.print(memInfo.getOtherSharedClean(i)); pw.print(',');
2196                pw.print(memInfo.getOtherPrivateDirty(i)); pw.print(',');
2197                pw.print(memInfo.getOtherPrivateClean(i)); pw.print(',');
2198                pw.print(memInfo.getOtherSwappedOut(i)); pw.print(',');
2199                if (memInfo.hasSwappedOutPss) {
2200                    pw.print(memInfo.getOtherSwappedOutPss(i)); pw.print(',');
2201                } else {
2202                    pw.print("N/A,");
2203                }
2204            }
2205            return;
2206        }
2207
2208        if (!dumpSummaryOnly) {
2209            if (dumpFullInfo) {
2210                printRow(pw, HEAP_FULL_COLUMN, "", "Pss", "Pss", "Shared", "Private",
2211                        "Shared", "Private", memInfo.hasSwappedOutPss ? "SwapPss" : "Swap",
2212                        "Heap", "Heap", "Heap");
2213                printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "Dirty",
2214                        "Clean", "Clean", "Dirty",
2215                        "Size", "Alloc", "Free");
2216                printRow(pw, HEAP_FULL_COLUMN, "", "------", "------", "------", "------",
2217                        "------", "------", "------", "------", "------", "------");
2218                printRow(pw, HEAP_FULL_COLUMN, "Native Heap", memInfo.nativePss,
2219                        memInfo.nativeSwappablePss, memInfo.nativeSharedDirty,
2220                        memInfo.nativePrivateDirty, memInfo.nativeSharedClean,
2221                        memInfo.nativePrivateClean, memInfo.hasSwappedOutPss ?
2222                        memInfo.nativeSwappedOut : memInfo.nativeSwappedOutPss,
2223                        nativeMax, nativeAllocated, nativeFree);
2224                printRow(pw, HEAP_FULL_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
2225                        memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty,
2226                        memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean,
2227                        memInfo.dalvikPrivateClean, memInfo.hasSwappedOutPss ?
2228                        memInfo.dalvikSwappedOut : memInfo.dalvikSwappedOutPss,
2229                        dalvikMax, dalvikAllocated, dalvikFree);
2230            } else {
2231                printRow(pw, HEAP_COLUMN, "", "Pss", "Private",
2232                        "Private", memInfo.hasSwappedOutPss ? "SwapPss" : "Swap",
2233                        "Heap", "Heap", "Heap");
2234                printRow(pw, HEAP_COLUMN, "", "Total", "Dirty",
2235                        "Clean", "Dirty", "Size", "Alloc", "Free");
2236                printRow(pw, HEAP_COLUMN, "", "------", "------", "------",
2237                        "------", "------", "------", "------", "------");
2238                printRow(pw, HEAP_COLUMN, "Native Heap", memInfo.nativePss,
2239                        memInfo.nativePrivateDirty,
2240                        memInfo.nativePrivateClean,
2241                        memInfo.hasSwappedOutPss ? memInfo.nativeSwappedOutPss :
2242                        memInfo.nativeSwappedOut,
2243                        nativeMax, nativeAllocated, nativeFree);
2244                printRow(pw, HEAP_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
2245                        memInfo.dalvikPrivateDirty,
2246                        memInfo.dalvikPrivateClean,
2247                        memInfo.hasSwappedOutPss ? memInfo.dalvikSwappedOutPss :
2248                        memInfo.dalvikSwappedOut,
2249                        dalvikMax, dalvikAllocated, dalvikFree);
2250            }
2251
2252            int otherPss = memInfo.otherPss;
2253            int otherSwappablePss = memInfo.otherSwappablePss;
2254            int otherSharedDirty = memInfo.otherSharedDirty;
2255            int otherPrivateDirty = memInfo.otherPrivateDirty;
2256            int otherSharedClean = memInfo.otherSharedClean;
2257            int otherPrivateClean = memInfo.otherPrivateClean;
2258            int otherSwappedOut = memInfo.otherSwappedOut;
2259            int otherSwappedOutPss = memInfo.otherSwappedOutPss;
2260
2261            for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
2262                final int myPss = memInfo.getOtherPss(i);
2263                final int mySwappablePss = memInfo.getOtherSwappablePss(i);
2264                final int mySharedDirty = memInfo.getOtherSharedDirty(i);
2265                final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
2266                final int mySharedClean = memInfo.getOtherSharedClean(i);
2267                final int myPrivateClean = memInfo.getOtherPrivateClean(i);
2268                final int mySwappedOut = memInfo.getOtherSwappedOut(i);
2269                final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
2270                if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
2271                        || mySharedClean != 0 || myPrivateClean != 0
2272                        || (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
2273                    if (dumpFullInfo) {
2274                        printRow(pw, HEAP_FULL_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
2275                                myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
2276                                mySharedClean, myPrivateClean,
2277                                memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
2278                                "", "", "");
2279                    } else {
2280                        printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
2281                                myPss, myPrivateDirty,
2282                                myPrivateClean,
2283                                memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
2284                                "", "", "");
2285                    }
2286                    otherPss -= myPss;
2287                    otherSwappablePss -= mySwappablePss;
2288                    otherSharedDirty -= mySharedDirty;
2289                    otherPrivateDirty -= myPrivateDirty;
2290                    otherSharedClean -= mySharedClean;
2291                    otherPrivateClean -= myPrivateClean;
2292                    otherSwappedOut -= mySwappedOut;
2293                    otherSwappedOutPss -= mySwappedOutPss;
2294                }
2295            }
2296
2297            if (dumpFullInfo) {
2298                printRow(pw, HEAP_FULL_COLUMN, "Unknown", otherPss, otherSwappablePss,
2299                        otherSharedDirty, otherPrivateDirty, otherSharedClean, otherPrivateClean,
2300                        memInfo.hasSwappedOutPss ? otherSwappedOutPss : otherSwappedOut,
2301                        "", "", "");
2302                printRow(pw, HEAP_FULL_COLUMN, "TOTAL", memInfo.getTotalPss(),
2303                        memInfo.getTotalSwappablePss(),
2304                        memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
2305                        memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(),
2306                        memInfo.hasSwappedOutPss ? memInfo.getTotalSwappedOutPss() :
2307                        memInfo.getTotalSwappedOut(),
2308                        nativeMax+dalvikMax, nativeAllocated+dalvikAllocated,
2309                        nativeFree+dalvikFree);
2310            } else {
2311                printRow(pw, HEAP_COLUMN, "Unknown", otherPss,
2312                        otherPrivateDirty, otherPrivateClean,
2313                        memInfo.hasSwappedOutPss ? otherSwappedOutPss : otherSwappedOut,
2314                        "", "", "");
2315                printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(),
2316                        memInfo.getTotalPrivateDirty(),
2317                        memInfo.getTotalPrivateClean(),
2318                        memInfo.hasSwappedOutPss ? memInfo.getTotalSwappedOutPss() :
2319                        memInfo.getTotalSwappedOut(),
2320                        nativeMax+dalvikMax,
2321                        nativeAllocated+dalvikAllocated, nativeFree+dalvikFree);
2322            }
2323
2324            if (dumpDalvik) {
2325                pw.println(" ");
2326                pw.println(" Dalvik Details");
2327
2328                for (int i=Debug.MemoryInfo.NUM_OTHER_STATS;
2329                     i<Debug.MemoryInfo.NUM_OTHER_STATS + Debug.MemoryInfo.NUM_DVK_STATS; i++) {
2330                    final int myPss = memInfo.getOtherPss(i);
2331                    final int mySwappablePss = memInfo.getOtherSwappablePss(i);
2332                    final int mySharedDirty = memInfo.getOtherSharedDirty(i);
2333                    final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
2334                    final int mySharedClean = memInfo.getOtherSharedClean(i);
2335                    final int myPrivateClean = memInfo.getOtherPrivateClean(i);
2336                    final int mySwappedOut = memInfo.getOtherSwappedOut(i);
2337                    final int mySwappedOutPss = memInfo.getOtherSwappedOutPss(i);
2338                    if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
2339                            || mySharedClean != 0 || myPrivateClean != 0
2340                            || (memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut) != 0) {
2341                        if (dumpFullInfo) {
2342                            printRow(pw, HEAP_FULL_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
2343                                    myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
2344                                    mySharedClean, myPrivateClean,
2345                                    memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
2346                                    "", "", "");
2347                        } else {
2348                            printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
2349                                    myPss, myPrivateDirty,
2350                                    myPrivateClean,
2351                                    memInfo.hasSwappedOutPss ? mySwappedOutPss : mySwappedOut,
2352                                    "", "", "");
2353                        }
2354                    }
2355                }
2356            }
2357        }
2358
2359        pw.println(" ");
2360        pw.println(" App Summary");
2361        printRow(pw, ONE_COUNT_COLUMN_HEADER, "", "Pss(KB)");
2362        printRow(pw, ONE_COUNT_COLUMN_HEADER, "", "------");
2363        printRow(pw, ONE_COUNT_COLUMN,
2364            "Java Heap:", memInfo.getSummaryJavaHeap());
2365        printRow(pw, ONE_COUNT_COLUMN,
2366            "Native Heap:", memInfo.getSummaryNativeHeap());
2367        printRow(pw, ONE_COUNT_COLUMN,
2368            "Code:", memInfo.getSummaryCode());
2369        printRow(pw, ONE_COUNT_COLUMN,
2370            "Stack:", memInfo.getSummaryStack());
2371        printRow(pw, ONE_COUNT_COLUMN,
2372            "Graphics:", memInfo.getSummaryGraphics());
2373        printRow(pw, ONE_COUNT_COLUMN,
2374            "Private Other:", memInfo.getSummaryPrivateOther());
2375        printRow(pw, ONE_COUNT_COLUMN,
2376            "System:", memInfo.getSummarySystem());
2377        pw.println(" ");
2378        if (memInfo.hasSwappedOutPss) {
2379            printRow(pw, TWO_COUNT_COLUMNS,
2380                "TOTAL:", memInfo.getSummaryTotalPss(),
2381                "TOTAL SWAP PSS:", memInfo.getSummaryTotalSwapPss());
2382        } else {
2383            printRow(pw, TWO_COUNT_COLUMNS,
2384                "TOTAL:", memInfo.getSummaryTotalPss(),
2385                "TOTAL SWAP (KB):", memInfo.getSummaryTotalSwap());
2386        }
2387    }
2388
2389    public void registerOnActivityPausedListener(Activity activity,
2390            OnActivityPausedListener listener) {
2391        synchronized (mOnPauseListeners) {
2392            ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity);
2393            if (list == null) {
2394                list = new ArrayList<OnActivityPausedListener>();
2395                mOnPauseListeners.put(activity, list);
2396            }
2397            list.add(listener);
2398        }
2399    }
2400
2401    public void unregisterOnActivityPausedListener(Activity activity,
2402            OnActivityPausedListener listener) {
2403        synchronized (mOnPauseListeners) {
2404            ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity);
2405            if (list != null) {
2406                list.remove(listener);
2407            }
2408        }
2409    }
2410
2411    public final ActivityInfo resolveActivityInfo(Intent intent) {
2412        ActivityInfo aInfo = intent.resolveActivityInfo(
2413                mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES);
2414        if (aInfo == null) {
2415            // Throw an exception.
2416            Instrumentation.checkStartActivityResult(
2417                    ActivityManager.START_CLASS_NOT_FOUND, intent);
2418        }
2419        return aInfo;
2420    }
2421
2422    public final Activity startActivityNow(Activity parent, String id,
2423        Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
2424        Activity.NonConfigurationInstances lastNonConfigurationInstances) {
2425        ActivityClientRecord r = new ActivityClientRecord();
2426            r.token = token;
2427            r.ident = 0;
2428            r.intent = intent;
2429            r.state = state;
2430            r.parent = parent;
2431            r.embeddedID = id;
2432            r.activityInfo = activityInfo;
2433            r.lastNonConfigurationInstances = lastNonConfigurationInstances;
2434        if (localLOGV) {
2435            ComponentName compname = intent.getComponent();
2436            String name;
2437            if (compname != null) {
2438                name = compname.toShortString();
2439            } else {
2440                name = "(Intent " + intent + ").getComponent() returned null";
2441            }
2442            Slog.v(TAG, "Performing launch: action=" + intent.getAction()
2443                    + ", comp=" + name
2444                    + ", token=" + token);
2445        }
2446        return performLaunchActivity(r, null);
2447    }
2448
2449    public final Activity getActivity(IBinder token) {
2450        return mActivities.get(token).activity;
2451    }
2452
2453    public final void sendActivityResult(
2454            IBinder token, String id, int requestCode,
2455            int resultCode, Intent data) {
2456        if (DEBUG_RESULTS) Slog.v(TAG, "sendActivityResult: id=" + id
2457                + " req=" + requestCode + " res=" + resultCode + " data=" + data);
2458        ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
2459        list.add(new ResultInfo(id, requestCode, resultCode, data));
2460        mAppThread.scheduleSendResult(token, list);
2461    }
2462
2463    private void sendMessage(int what, Object obj) {
2464        sendMessage(what, obj, 0, 0, false);
2465    }
2466
2467    private void sendMessage(int what, Object obj, int arg1) {
2468        sendMessage(what, obj, arg1, 0, false);
2469    }
2470
2471    private void sendMessage(int what, Object obj, int arg1, int arg2) {
2472        sendMessage(what, obj, arg1, arg2, false);
2473    }
2474
2475    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
2476        if (DEBUG_MESSAGES) Slog.v(
2477            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
2478            + ": " + arg1 + " / " + obj);
2479        Message msg = Message.obtain();
2480        msg.what = what;
2481        msg.obj = obj;
2482        msg.arg1 = arg1;
2483        msg.arg2 = arg2;
2484        if (async) {
2485            msg.setAsynchronous(true);
2486        }
2487        mH.sendMessage(msg);
2488    }
2489
2490    private void sendMessage(int what, Object obj, int arg1, int arg2, int seq) {
2491        if (DEBUG_MESSAGES) Slog.v(
2492                TAG, "SCHEDULE " + mH.codeToString(what) + " arg1=" + arg1 + " arg2=" + arg2 +
2493                        "seq= " + seq);
2494        Message msg = Message.obtain();
2495        msg.what = what;
2496        SomeArgs args = SomeArgs.obtain();
2497        args.arg1 = obj;
2498        args.argi1 = arg1;
2499        args.argi2 = arg2;
2500        args.argi3 = seq;
2501        msg.obj = args;
2502        mH.sendMessage(msg);
2503    }
2504
2505    final void scheduleContextCleanup(ContextImpl context, String who,
2506            String what) {
2507        ContextCleanupInfo cci = new ContextCleanupInfo();
2508        cci.context = context;
2509        cci.who = who;
2510        cci.what = what;
2511        sendMessage(H.CLEAN_UP_CONTEXT, cci);
2512    }
2513
2514    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
2515        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
2516
2517        ActivityInfo aInfo = r.activityInfo;
2518        if (r.packageInfo == null) {
2519            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
2520                    Context.CONTEXT_INCLUDE_CODE);
2521        }
2522
2523        ComponentName component = r.intent.getComponent();
2524        if (component == null) {
2525            component = r.intent.resolveActivity(
2526                mInitialApplication.getPackageManager());
2527            r.intent.setComponent(component);
2528        }
2529
2530        if (r.activityInfo.targetActivity != null) {
2531            component = new ComponentName(r.activityInfo.packageName,
2532                    r.activityInfo.targetActivity);
2533        }
2534
2535        Activity activity = null;
2536        try {
2537            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
2538            activity = mInstrumentation.newActivity(
2539                    cl, component.getClassName(), r.intent);
2540            StrictMode.incrementExpectedActivityCount(activity.getClass());
2541            r.intent.setExtrasClassLoader(cl);
2542            r.intent.prepareToEnterProcess();
2543            if (r.state != null) {
2544                r.state.setClassLoader(cl);
2545            }
2546        } catch (Exception e) {
2547            if (!mInstrumentation.onException(activity, e)) {
2548                throw new RuntimeException(
2549                    "Unable to instantiate activity " + component
2550                    + ": " + e.toString(), e);
2551            }
2552        }
2553
2554        try {
2555            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
2556
2557            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
2558            if (localLOGV) Slog.v(
2559                    TAG, r + ": app=" + app
2560                    + ", appName=" + app.getPackageName()
2561                    + ", pkg=" + r.packageInfo.getPackageName()
2562                    + ", comp=" + r.intent.getComponent().toShortString()
2563                    + ", dir=" + r.packageInfo.getAppDir());
2564
2565            if (activity != null) {
2566                Context appContext = createBaseContextForActivity(r, activity);
2567                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
2568                Configuration config = new Configuration(mCompatConfiguration);
2569                if (r.overrideConfig != null) {
2570                    config.updateFrom(r.overrideConfig);
2571                }
2572                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
2573                        + r.activityInfo.name + " with config " + config);
2574                Window window = null;
2575                if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
2576                    window = r.mPendingRemoveWindow;
2577                    r.mPendingRemoveWindow = null;
2578                    r.mPendingRemoveWindowManager = null;
2579                }
2580                activity.attach(appContext, this, getInstrumentation(), r.token,
2581                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
2582                        r.embeddedID, r.lastNonConfigurationInstances, config,
2583                        r.referrer, r.voiceInteractor, window);
2584
2585                if (customIntent != null) {
2586                    activity.mIntent = customIntent;
2587                }
2588                r.lastNonConfigurationInstances = null;
2589                activity.mStartedActivity = false;
2590                int theme = r.activityInfo.getThemeResource();
2591                if (theme != 0) {
2592                    activity.setTheme(theme);
2593                }
2594
2595                activity.mCalled = false;
2596                if (r.isPersistable()) {
2597                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
2598                } else {
2599                    mInstrumentation.callActivityOnCreate(activity, r.state);
2600                }
2601                if (!activity.mCalled) {
2602                    throw new SuperNotCalledException(
2603                        "Activity " + r.intent.getComponent().toShortString() +
2604                        " did not call through to super.onCreate()");
2605                }
2606                r.activity = activity;
2607                r.stopped = true;
2608                if (!r.activity.mFinished) {
2609                    activity.performStart();
2610                    r.stopped = false;
2611                }
2612                if (!r.activity.mFinished) {
2613                    if (r.isPersistable()) {
2614                        if (r.state != null || r.persistentState != null) {
2615                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
2616                                    r.persistentState);
2617                        }
2618                    } else if (r.state != null) {
2619                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
2620                    }
2621                }
2622                if (!r.activity.mFinished) {
2623                    activity.mCalled = false;
2624                    if (r.isPersistable()) {
2625                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
2626                                r.persistentState);
2627                    } else {
2628                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
2629                    }
2630                    if (!activity.mCalled) {
2631                        throw new SuperNotCalledException(
2632                            "Activity " + r.intent.getComponent().toShortString() +
2633                            " did not call through to super.onPostCreate()");
2634                    }
2635                }
2636            }
2637            r.paused = true;
2638
2639            mActivities.put(r.token, r);
2640
2641        } catch (SuperNotCalledException e) {
2642            throw e;
2643
2644        } catch (Exception e) {
2645            if (!mInstrumentation.onException(activity, e)) {
2646                throw new RuntimeException(
2647                    "Unable to start activity " + component
2648                    + ": " + e.toString(), e);
2649            }
2650        }
2651
2652        return activity;
2653    }
2654
2655    private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
2656        int displayId = Display.DEFAULT_DISPLAY;
2657        try {
2658            displayId = ActivityManagerNative.getDefault().getActivityDisplayId(r.token);
2659        } catch (RemoteException e) {
2660            throw e.rethrowFromSystemServer();
2661        }
2662
2663        ContextImpl appContext = ContextImpl.createActivityContext(
2664                this, r.packageInfo, r.token, displayId, r.overrideConfig);
2665        appContext.setOuterContext(activity);
2666        Context baseContext = appContext;
2667
2668        final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
2669        // For debugging purposes, if the activity's package name contains the value of
2670        // the "debug.use-second-display" system property as a substring, then show
2671        // its content on a secondary display if there is one.
2672        String pkgName = SystemProperties.get("debug.second-display.pkg");
2673        if (pkgName != null && !pkgName.isEmpty()
2674                && r.packageInfo.mPackageName.contains(pkgName)) {
2675            for (int id : dm.getDisplayIds()) {
2676                if (id != Display.DEFAULT_DISPLAY) {
2677                    Display display =
2678                            dm.getCompatibleDisplay(id, appContext.getDisplayAdjustments(id));
2679                    baseContext = appContext.createDisplayContext(display);
2680                    break;
2681                }
2682            }
2683        }
2684        return baseContext;
2685    }
2686
2687    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
2688        // If we are getting ready to gc after going to the background, well
2689        // we are back active so skip it.
2690        unscheduleGcIdler();
2691        mSomeActivitiesChanged = true;
2692
2693        if (r.profilerInfo != null) {
2694            mProfiler.setProfiler(r.profilerInfo);
2695            mProfiler.startProfiling();
2696        }
2697
2698        // Make sure we are running with the most recent config.
2699        handleConfigurationChanged(null, null);
2700
2701        if (localLOGV) Slog.v(
2702            TAG, "Handling launch of " + r);
2703
2704        // Initialize before creating the activity
2705        WindowManagerGlobal.initialize();
2706
2707        Activity a = performLaunchActivity(r, customIntent);
2708
2709        if (a != null) {
2710            r.createdConfig = new Configuration(mConfiguration);
2711            reportSizeConfigurations(r);
2712            Bundle oldState = r.state;
2713            handleResumeActivity(r.token, false, r.isForward,
2714                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
2715
2716            if (!r.activity.mFinished && r.startsNotResumed) {
2717                // The activity manager actually wants this one to start out paused, because it
2718                // needs to be visible but isn't in the foreground. We accomplish this by going
2719                // through the normal startup (because activities expect to go through onResume()
2720                // the first time they run, before their window is displayed), and then pausing it.
2721                // However, in this case we do -not- need to do the full pause cycle (of freezing
2722                // and such) because the activity manager assumes it can just retain the current
2723                // state it has.
2724                performPauseActivityIfNeeded(r, reason);
2725
2726                // We need to keep around the original state, in case we need to be created again.
2727                // But we only do this for pre-Honeycomb apps, which always save their state when
2728                // pausing, so we can not have them save their state when restarting from a paused
2729                // state. For HC and later, we want to (and can) let the state be saved as the
2730                // normal part of stopping the activity.
2731                if (r.isPreHoneycomb()) {
2732                    r.state = oldState;
2733                }
2734            }
2735        } else {
2736            // If there was an error, for any reason, tell the activity manager to stop us.
2737            try {
2738                ActivityManagerNative.getDefault()
2739                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
2740                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
2741            } catch (RemoteException ex) {
2742                throw ex.rethrowFromSystemServer();
2743            }
2744        }
2745    }
2746
2747    private void reportSizeConfigurations(ActivityClientRecord r) {
2748        Configuration[] configurations = r.activity.getResources().getSizeConfigurations();
2749        if (configurations == null) {
2750            return;
2751        }
2752        SparseIntArray horizontal = new SparseIntArray();
2753        SparseIntArray vertical = new SparseIntArray();
2754        SparseIntArray smallest = new SparseIntArray();
2755        for (int i = configurations.length - 1; i >= 0; i--) {
2756            Configuration config = configurations[i];
2757            if (config.screenHeightDp != Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
2758                vertical.put(config.screenHeightDp, 0);
2759            }
2760            if (config.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
2761                horizontal.put(config.screenWidthDp, 0);
2762            }
2763            if (config.smallestScreenWidthDp != Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
2764                smallest.put(config.smallestScreenWidthDp, 0);
2765            }
2766        }
2767        try {
2768            ActivityManagerNative.getDefault().reportSizeConfigurations(r.token,
2769                    horizontal.copyKeys(), vertical.copyKeys(), smallest.copyKeys());
2770        } catch (RemoteException ex) {
2771            throw ex.rethrowFromSystemServer();
2772        }
2773
2774    }
2775
2776    private void deliverNewIntents(ActivityClientRecord r, List<ReferrerIntent> intents) {
2777        final int N = intents.size();
2778        for (int i=0; i<N; i++) {
2779            ReferrerIntent intent = intents.get(i);
2780            intent.setExtrasClassLoader(r.activity.getClassLoader());
2781            intent.prepareToEnterProcess();
2782            r.activity.mFragments.noteStateNotSaved();
2783            mInstrumentation.callActivityOnNewIntent(r.activity, intent);
2784        }
2785    }
2786
2787    public final void performNewIntents(IBinder token, List<ReferrerIntent> intents) {
2788        ActivityClientRecord r = mActivities.get(token);
2789        if (r != null) {
2790            final boolean resumed = !r.paused;
2791            if (resumed) {
2792                r.activity.mTemporaryPause = true;
2793                mInstrumentation.callActivityOnPause(r.activity);
2794            }
2795            deliverNewIntents(r, intents);
2796            if (resumed) {
2797                r.activity.performResume();
2798                r.activity.mTemporaryPause = false;
2799            }
2800        }
2801    }
2802
2803    private void handleNewIntent(NewIntentData data) {
2804        performNewIntents(data.token, data.intents);
2805    }
2806
2807    public void handleRequestAssistContextExtras(RequestAssistContextExtras cmd) {
2808        if (mLastSessionId != cmd.sessionId) {
2809            // Clear the existing structures
2810            mLastSessionId = cmd.sessionId;
2811            for (int i = mLastAssistStructures.size() - 1; i >= 0; i--) {
2812                AssistStructure structure = mLastAssistStructures.get(i).get();
2813                if (structure != null) {
2814                    structure.clearSendChannel();
2815                }
2816                mLastAssistStructures.remove(i);
2817            }
2818        }
2819        Bundle data = new Bundle();
2820        AssistStructure structure = null;
2821        AssistContent content = new AssistContent();
2822        ActivityClientRecord r = mActivities.get(cmd.activityToken);
2823        Uri referrer = null;
2824        if (r != null) {
2825            r.activity.getApplication().dispatchOnProvideAssistData(r.activity, data);
2826            r.activity.onProvideAssistData(data);
2827            referrer = r.activity.onProvideReferrer();
2828            if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL) {
2829                structure = new AssistStructure(r.activity);
2830                Intent activityIntent = r.activity.getIntent();
2831                if (activityIntent != null && (r.window == null ||
2832                        (r.window.getAttributes().flags
2833                                & WindowManager.LayoutParams.FLAG_SECURE) == 0)) {
2834                    Intent intent = new Intent(activityIntent);
2835                    intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
2836                            | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION));
2837                    intent.removeUnsafeExtras();
2838                    content.setDefaultIntent(intent);
2839                } else {
2840                    content.setDefaultIntent(new Intent());
2841                }
2842                r.activity.onProvideAssistContent(content);
2843            }
2844        }
2845        if (structure == null) {
2846            structure = new AssistStructure();
2847        }
2848        mLastAssistStructures.add(new WeakReference<>(structure));
2849        IActivityManager mgr = ActivityManagerNative.getDefault();
2850        try {
2851            mgr.reportAssistContextExtras(cmd.requestToken, data, structure, content, referrer);
2852        } catch (RemoteException e) {
2853            throw e.rethrowFromSystemServer();
2854        }
2855    }
2856
2857    public void handleTranslucentConversionComplete(IBinder token, boolean drawComplete) {
2858        ActivityClientRecord r = mActivities.get(token);
2859        if (r != null) {
2860            r.activity.onTranslucentConversionComplete(drawComplete);
2861        }
2862    }
2863
2864    public void onNewActivityOptions(IBinder token, ActivityOptions options) {
2865        ActivityClientRecord r = mActivities.get(token);
2866        if (r != null) {
2867            r.activity.onNewActivityOptions(options);
2868        }
2869    }
2870
2871    public void handleCancelVisibleBehind(IBinder token) {
2872        ActivityClientRecord r = mActivities.get(token);
2873        if (r != null) {
2874            mSomeActivitiesChanged = true;
2875            final Activity activity = r.activity;
2876            if (activity.mVisibleBehind) {
2877                activity.mCalled = false;
2878                activity.onVisibleBehindCanceled();
2879                // Tick, tick, tick. The activity has 500 msec to return or it will be destroyed.
2880                if (!activity.mCalled) {
2881                    throw new SuperNotCalledException("Activity " + activity.getLocalClassName() +
2882                            " did not call through to super.onVisibleBehindCanceled()");
2883                }
2884                activity.mVisibleBehind = false;
2885            }
2886        }
2887        try {
2888            ActivityManagerNative.getDefault().backgroundResourcesReleased(token);
2889        } catch (RemoteException e) {
2890            throw e.rethrowFromSystemServer();
2891        }
2892    }
2893
2894    public void handleOnBackgroundVisibleBehindChanged(IBinder token, boolean visible) {
2895        ActivityClientRecord r = mActivities.get(token);
2896        if (r != null) {
2897            r.activity.onBackgroundVisibleBehindChanged(visible);
2898        }
2899    }
2900
2901    public void handleInstallProvider(ProviderInfo info) {
2902        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
2903        try {
2904            installContentProviders(mInitialApplication, Lists.newArrayList(info));
2905        } finally {
2906            StrictMode.setThreadPolicy(oldPolicy);
2907        }
2908    }
2909
2910    private void handleEnterAnimationComplete(IBinder token) {
2911        ActivityClientRecord r = mActivities.get(token);
2912        if (r != null) {
2913            r.activity.dispatchEnterAnimationComplete();
2914        }
2915    }
2916
2917    private void handleStartBinderTracking() {
2918        Binder.enableTracing();
2919    }
2920
2921    private void handleStopBinderTrackingAndDump(ParcelFileDescriptor fd) {
2922        try {
2923            Binder.disableTracing();
2924            Binder.getTransactionTracker().writeTracesToFile(fd);
2925        } finally {
2926            IoUtils.closeQuietly(fd);
2927            Binder.getTransactionTracker().clearTraces();
2928        }
2929    }
2930
2931    private void handleMultiWindowModeChanged(IBinder token, boolean isInMultiWindowMode) {
2932        final ActivityClientRecord r = mActivities.get(token);
2933        if (r != null) {
2934            r.activity.dispatchMultiWindowModeChanged(isInMultiWindowMode);
2935        }
2936    }
2937
2938    private void handlePictureInPictureModeChanged(IBinder token, boolean isInPipMode) {
2939        final ActivityClientRecord r = mActivities.get(token);
2940        if (r != null) {
2941            r.activity.dispatchPictureInPictureModeChanged(isInPipMode);
2942        }
2943    }
2944
2945    private void handleLocalVoiceInteractionStarted(IBinder token, IVoiceInteractor interactor) {
2946        final ActivityClientRecord r = mActivities.get(token);
2947        if (r != null) {
2948            r.voiceInteractor = interactor;
2949            r.activity.setVoiceInteractor(interactor);
2950            if (interactor == null) {
2951                r.activity.onLocalVoiceInteractionStopped();
2952            } else {
2953                r.activity.onLocalVoiceInteractionStarted();
2954            }
2955        }
2956    }
2957
2958    private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>();
2959
2960    /**
2961     * Return the Intent that's currently being handled by a
2962     * BroadcastReceiver on this thread, or null if none.
2963     * @hide
2964     */
2965    public static Intent getIntentBeingBroadcast() {
2966        return sCurrentBroadcastIntent.get();
2967    }
2968
2969    private void handleReceiver(ReceiverData data) {
2970        // If we are getting ready to gc after going to the background, well
2971        // we are back active so skip it.
2972        unscheduleGcIdler();
2973
2974        String component = data.intent.getComponent().getClassName();
2975
2976        LoadedApk packageInfo = getPackageInfoNoCheck(
2977                data.info.applicationInfo, data.compatInfo);
2978
2979        IActivityManager mgr = ActivityManagerNative.getDefault();
2980
2981        BroadcastReceiver receiver;
2982        try {
2983            java.lang.ClassLoader cl = packageInfo.getClassLoader();
2984            data.intent.setExtrasClassLoader(cl);
2985            data.intent.prepareToEnterProcess();
2986            data.setExtrasClassLoader(cl);
2987            receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
2988        } catch (Exception e) {
2989            if (DEBUG_BROADCAST) Slog.i(TAG,
2990                    "Finishing failed broadcast to " + data.intent.getComponent());
2991            data.sendFinished(mgr);
2992            throw new RuntimeException(
2993                "Unable to instantiate receiver " + component
2994                + ": " + e.toString(), e);
2995        }
2996
2997        try {
2998            Application app = packageInfo.makeApplication(false, mInstrumentation);
2999
3000            if (localLOGV) Slog.v(
3001                TAG, "Performing receive of " + data.intent
3002                + ": app=" + app
3003                + ", appName=" + app.getPackageName()
3004                + ", pkg=" + packageInfo.getPackageName()
3005                + ", comp=" + data.intent.getComponent().toShortString()
3006                + ", dir=" + packageInfo.getAppDir());
3007
3008            ContextImpl context = (ContextImpl)app.getBaseContext();
3009            sCurrentBroadcastIntent.set(data.intent);
3010            receiver.setPendingResult(data);
3011            receiver.onReceive(context.getReceiverRestrictedContext(),
3012                    data.intent);
3013        } catch (Exception e) {
3014            if (DEBUG_BROADCAST) Slog.i(TAG,
3015                    "Finishing failed broadcast to " + data.intent.getComponent());
3016            data.sendFinished(mgr);
3017            if (!mInstrumentation.onException(receiver, e)) {
3018                throw new RuntimeException(
3019                    "Unable to start receiver " + component
3020                    + ": " + e.toString(), e);
3021            }
3022        } finally {
3023            sCurrentBroadcastIntent.set(null);
3024        }
3025
3026        if (receiver.getPendingResult() != null) {
3027            data.finish();
3028        }
3029    }
3030
3031    // Instantiate a BackupAgent and tell it that it's alive
3032    private void handleCreateBackupAgent(CreateBackupAgentData data) {
3033        if (DEBUG_BACKUP) Slog.v(TAG, "handleCreateBackupAgent: " + data);
3034
3035        // Sanity check the requested target package's uid against ours
3036        try {
3037            PackageInfo requestedPackage = getPackageManager().getPackageInfo(
3038                    data.appInfo.packageName, 0, UserHandle.myUserId());
3039            if (requestedPackage.applicationInfo.uid != Process.myUid()) {
3040                Slog.w(TAG, "Asked to instantiate non-matching package "
3041                        + data.appInfo.packageName);
3042                return;
3043            }
3044        } catch (RemoteException e) {
3045            throw e.rethrowFromSystemServer();
3046        }
3047
3048        // no longer idle; we have backup work to do
3049        unscheduleGcIdler();
3050
3051        // instantiate the BackupAgent class named in the manifest
3052        LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
3053        String packageName = packageInfo.mPackageName;
3054        if (packageName == null) {
3055            Slog.d(TAG, "Asked to create backup agent for nonexistent package");
3056            return;
3057        }
3058
3059        String classname = data.appInfo.backupAgentName;
3060        // full backup operation but no app-supplied agent?  use the default implementation
3061        if (classname == null && (data.backupMode == IApplicationThread.BACKUP_MODE_FULL
3062                || data.backupMode == IApplicationThread.BACKUP_MODE_RESTORE_FULL)) {
3063            classname = "android.app.backup.FullBackupAgent";
3064        }
3065
3066        try {
3067            IBinder binder = null;
3068            BackupAgent agent = mBackupAgents.get(packageName);
3069            if (agent != null) {
3070                // reusing the existing instance
3071                if (DEBUG_BACKUP) {
3072                    Slog.v(TAG, "Reusing existing agent instance");
3073                }
3074                binder = agent.onBind();
3075            } else {
3076                try {
3077                    if (DEBUG_BACKUP) Slog.v(TAG, "Initializing agent class " + classname);
3078
3079                    java.lang.ClassLoader cl = packageInfo.getClassLoader();
3080                    agent = (BackupAgent) cl.loadClass(classname).newInstance();
3081
3082                    // set up the agent's context
3083                    ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
3084                    context.setOuterContext(agent);
3085                    agent.attach(context);
3086
3087                    agent.onCreate();
3088                    binder = agent.onBind();
3089                    mBackupAgents.put(packageName, agent);
3090                } catch (Exception e) {
3091                    // If this is during restore, fail silently; otherwise go
3092                    // ahead and let the user see the crash.
3093                    Slog.e(TAG, "Agent threw during creation: " + e);
3094                    if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE
3095                            && data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE_FULL) {
3096                        throw e;
3097                    }
3098                    // falling through with 'binder' still null
3099                }
3100            }
3101
3102            // tell the OS that we're live now
3103            try {
3104                ActivityManagerNative.getDefault().backupAgentCreated(packageName, binder);
3105            } catch (RemoteException e) {
3106                throw e.rethrowFromSystemServer();
3107            }
3108        } catch (Exception e) {
3109            throw new RuntimeException("Unable to create BackupAgent "
3110                    + classname + ": " + e.toString(), e);
3111        }
3112    }
3113
3114    // Tear down a BackupAgent
3115    private void handleDestroyBackupAgent(CreateBackupAgentData data) {
3116        if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
3117
3118        LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
3119        String packageName = packageInfo.mPackageName;
3120        BackupAgent agent = mBackupAgents.get(packageName);
3121        if (agent != null) {
3122            try {
3123                agent.onDestroy();
3124            } catch (Exception e) {
3125                Slog.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo);
3126                e.printStackTrace();
3127            }
3128            mBackupAgents.remove(packageName);
3129        } else {
3130            Slog.w(TAG, "Attempt to destroy unknown backup agent " + data);
3131        }
3132    }
3133
3134    private void handleCreateService(CreateServiceData data) {
3135        // If we are getting ready to gc after going to the background, well
3136        // we are back active so skip it.
3137        unscheduleGcIdler();
3138
3139        LoadedApk packageInfo = getPackageInfoNoCheck(
3140                data.info.applicationInfo, data.compatInfo);
3141        Service service = null;
3142        try {
3143            java.lang.ClassLoader cl = packageInfo.getClassLoader();
3144            service = (Service) cl.loadClass(data.info.name).newInstance();
3145        } catch (Exception e) {
3146            if (!mInstrumentation.onException(service, e)) {
3147                throw new RuntimeException(
3148                    "Unable to instantiate service " + data.info.name
3149                    + ": " + e.toString(), e);
3150            }
3151        }
3152
3153        try {
3154            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
3155
3156            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
3157            context.setOuterContext(service);
3158
3159            Application app = packageInfo.makeApplication(false, mInstrumentation);
3160            service.attach(context, this, data.info.name, data.token, app,
3161                    ActivityManagerNative.getDefault());
3162            service.onCreate();
3163            mServices.put(data.token, service);
3164            try {
3165                ActivityManagerNative.getDefault().serviceDoneExecuting(
3166                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
3167            } catch (RemoteException e) {
3168                throw e.rethrowFromSystemServer();
3169            }
3170        } catch (Exception e) {
3171            if (!mInstrumentation.onException(service, e)) {
3172                throw new RuntimeException(
3173                    "Unable to create service " + data.info.name
3174                    + ": " + e.toString(), e);
3175            }
3176        }
3177    }
3178
3179    private void handleBindService(BindServiceData data) {
3180        Service s = mServices.get(data.token);
3181        if (DEBUG_SERVICE)
3182            Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
3183        if (s != null) {
3184            try {
3185                data.intent.setExtrasClassLoader(s.getClassLoader());
3186                data.intent.prepareToEnterProcess();
3187                try {
3188                    if (!data.rebind) {
3189                        IBinder binder = s.onBind(data.intent);
3190                        ActivityManagerNative.getDefault().publishService(
3191                                data.token, data.intent, binder);
3192                    } else {
3193                        s.onRebind(data.intent);
3194                        ActivityManagerNative.getDefault().serviceDoneExecuting(
3195                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
3196                    }
3197                    ensureJitEnabled();
3198                } catch (RemoteException ex) {
3199                    throw ex.rethrowFromSystemServer();
3200                }
3201            } catch (Exception e) {
3202                if (!mInstrumentation.onException(s, e)) {
3203                    throw new RuntimeException(
3204                            "Unable to bind to service " + s
3205                            + " with " + data.intent + ": " + e.toString(), e);
3206                }
3207            }
3208        }
3209    }
3210
3211    private void handleUnbindService(BindServiceData data) {
3212        Service s = mServices.get(data.token);
3213        if (s != null) {
3214            try {
3215                data.intent.setExtrasClassLoader(s.getClassLoader());
3216                data.intent.prepareToEnterProcess();
3217                boolean doRebind = s.onUnbind(data.intent);
3218                try {
3219                    if (doRebind) {
3220                        ActivityManagerNative.getDefault().unbindFinished(
3221                                data.token, data.intent, doRebind);
3222                    } else {
3223                        ActivityManagerNative.getDefault().serviceDoneExecuting(
3224                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
3225                    }
3226                } catch (RemoteException ex) {
3227                    throw ex.rethrowFromSystemServer();
3228                }
3229            } catch (Exception e) {
3230                if (!mInstrumentation.onException(s, e)) {
3231                    throw new RuntimeException(
3232                            "Unable to unbind to service " + s
3233                            + " with " + data.intent + ": " + e.toString(), e);
3234                }
3235            }
3236        }
3237    }
3238
3239    private void handleDumpService(DumpComponentInfo info) {
3240        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
3241        try {
3242            Service s = mServices.get(info.token);
3243            if (s != null) {
3244                PrintWriter pw = new FastPrintWriter(new FileOutputStream(
3245                        info.fd.getFileDescriptor()));
3246                s.dump(info.fd.getFileDescriptor(), pw, info.args);
3247                pw.flush();
3248            }
3249        } finally {
3250            IoUtils.closeQuietly(info.fd);
3251            StrictMode.setThreadPolicy(oldPolicy);
3252        }
3253    }
3254
3255    private void handleDumpActivity(DumpComponentInfo info) {
3256        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
3257        try {
3258            ActivityClientRecord r = mActivities.get(info.token);
3259            if (r != null && r.activity != null) {
3260                PrintWriter pw = new FastPrintWriter(new FileOutputStream(
3261                        info.fd.getFileDescriptor()));
3262                r.activity.dump(info.prefix, info.fd.getFileDescriptor(), pw, info.args);
3263                pw.flush();
3264            }
3265        } finally {
3266            IoUtils.closeQuietly(info.fd);
3267            StrictMode.setThreadPolicy(oldPolicy);
3268        }
3269    }
3270
3271    private void handleDumpProvider(DumpComponentInfo info) {
3272        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
3273        try {
3274            ProviderClientRecord r = mLocalProviders.get(info.token);
3275            if (r != null && r.mLocalProvider != null) {
3276                PrintWriter pw = new FastPrintWriter(new FileOutputStream(
3277                        info.fd.getFileDescriptor()));
3278                r.mLocalProvider.dump(info.fd.getFileDescriptor(), pw, info.args);
3279                pw.flush();
3280            }
3281        } finally {
3282            IoUtils.closeQuietly(info.fd);
3283            StrictMode.setThreadPolicy(oldPolicy);
3284        }
3285    }
3286
3287    private void handleServiceArgs(ServiceArgsData data) {
3288        Service s = mServices.get(data.token);
3289        if (s != null) {
3290            try {
3291                if (data.args != null) {
3292                    data.args.setExtrasClassLoader(s.getClassLoader());
3293                    data.args.prepareToEnterProcess();
3294                }
3295                int res;
3296                if (!data.taskRemoved) {
3297                    res = s.onStartCommand(data.args, data.flags, data.startId);
3298                } else {
3299                    s.onTaskRemoved(data.args);
3300                    res = Service.START_TASK_REMOVED_COMPLETE;
3301                }
3302
3303                QueuedWork.waitToFinish();
3304
3305                try {
3306                    ActivityManagerNative.getDefault().serviceDoneExecuting(
3307                            data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
3308                } catch (RemoteException e) {
3309                    throw e.rethrowFromSystemServer();
3310                }
3311                ensureJitEnabled();
3312            } catch (Exception e) {
3313                if (!mInstrumentation.onException(s, e)) {
3314                    throw new RuntimeException(
3315                            "Unable to start service " + s
3316                            + " with " + data.args + ": " + e.toString(), e);
3317                }
3318            }
3319        }
3320    }
3321
3322    private void handleStopService(IBinder token) {
3323        Service s = mServices.remove(token);
3324        if (s != null) {
3325            try {
3326                if (localLOGV) Slog.v(TAG, "Destroying service " + s);
3327                s.onDestroy();
3328                Context context = s.getBaseContext();
3329                if (context instanceof ContextImpl) {
3330                    final String who = s.getClassName();
3331                    ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
3332                }
3333
3334                QueuedWork.waitToFinish();
3335
3336                try {
3337                    ActivityManagerNative.getDefault().serviceDoneExecuting(
3338                            token, SERVICE_DONE_EXECUTING_STOP, 0, 0);
3339                } catch (RemoteException e) {
3340                    throw e.rethrowFromSystemServer();
3341                }
3342            } catch (Exception e) {
3343                if (!mInstrumentation.onException(s, e)) {
3344                    throw new RuntimeException(
3345                            "Unable to stop service " + s
3346                            + ": " + e.toString(), e);
3347                }
3348                Slog.i(TAG, "handleStopService: exception for " + token, e);
3349            }
3350        } else {
3351            Slog.i(TAG, "handleStopService: token=" + token + " not found.");
3352        }
3353        //Slog.i(TAG, "Running services: " + mServices);
3354    }
3355
3356    public final ActivityClientRecord performResumeActivity(IBinder token,
3357            boolean clearHide, String reason) {
3358        ActivityClientRecord r = mActivities.get(token);
3359        if (localLOGV) Slog.v(TAG, "Performing resume of " + r
3360                + " finished=" + r.activity.mFinished);
3361        if (r != null && !r.activity.mFinished) {
3362            if (clearHide) {
3363                r.hideForNow = false;
3364                r.activity.mStartedActivity = false;
3365            }
3366            try {
3367                r.activity.onStateNotSaved();
3368                r.activity.mFragments.noteStateNotSaved();
3369                if (r.pendingIntents != null) {
3370                    deliverNewIntents(r, r.pendingIntents);
3371                    r.pendingIntents = null;
3372                }
3373                if (r.pendingResults != null) {
3374                    deliverResults(r, r.pendingResults);
3375                    r.pendingResults = null;
3376                }
3377                r.activity.performResume();
3378
3379                // If there is a pending local relaunch that was requested when the activity was
3380                // paused, it will put the activity into paused state when it finally happens.
3381                // Since the activity resumed before being relaunched, we don't want that to happen,
3382                // so we need to clear the request to relaunch paused.
3383                for (int i = mRelaunchingActivities.size() - 1; i >= 0; i--) {
3384                    final ActivityClientRecord relaunching = mRelaunchingActivities.get(i);
3385                    if (relaunching.token == r.token
3386                            && relaunching.onlyLocalRequest && relaunching.startsNotResumed) {
3387                        relaunching.startsNotResumed = false;
3388                    }
3389                }
3390
3391                EventLog.writeEvent(LOG_AM_ON_RESUME_CALLED, UserHandle.myUserId(),
3392                        r.activity.getComponentName().getClassName(), reason);
3393
3394                r.paused = false;
3395                r.stopped = false;
3396                r.state = null;
3397                r.persistentState = null;
3398            } catch (Exception e) {
3399                if (!mInstrumentation.onException(r.activity, e)) {
3400                    throw new RuntimeException(
3401                        "Unable to resume activity "
3402                        + r.intent.getComponent().toShortString()
3403                        + ": " + e.toString(), e);
3404                }
3405            }
3406        }
3407        return r;
3408    }
3409
3410    static final void cleanUpPendingRemoveWindows(ActivityClientRecord r, boolean force) {
3411        if (r.mPreserveWindow && !force) {
3412            return;
3413        }
3414        if (r.mPendingRemoveWindow != null) {
3415            r.mPendingRemoveWindowManager.removeViewImmediate(
3416                    r.mPendingRemoveWindow.getDecorView());
3417            IBinder wtoken = r.mPendingRemoveWindow.getDecorView().getWindowToken();
3418            if (wtoken != null) {
3419                WindowManagerGlobal.getInstance().closeAll(wtoken,
3420                        r.activity.getClass().getName(), "Activity");
3421            }
3422        }
3423        r.mPendingRemoveWindow = null;
3424        r.mPendingRemoveWindowManager = null;
3425    }
3426
3427    final void handleResumeActivity(IBinder token,
3428            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
3429        ActivityClientRecord r = mActivities.get(token);
3430        if (!checkAndUpdateLifecycleSeq(seq, r, "resumeActivity")) {
3431            return;
3432        }
3433
3434        // If we are getting ready to gc after going to the background, well
3435        // we are back active so skip it.
3436        unscheduleGcIdler();
3437        mSomeActivitiesChanged = true;
3438
3439        // TODO Push resumeArgs into the activity for consideration
3440        r = performResumeActivity(token, clearHide, reason);
3441
3442        if (r != null) {
3443            final Activity a = r.activity;
3444
3445            if (localLOGV) Slog.v(
3446                TAG, "Resume " + r + " started activity: " +
3447                a.mStartedActivity + ", hideForNow: " + r.hideForNow
3448                + ", finished: " + a.mFinished);
3449
3450            final int forwardBit = isForward ?
3451                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
3452
3453            // If the window hasn't yet been added to the window manager,
3454            // and this guy didn't finish itself or start another activity,
3455            // then go ahead and add the window.
3456            boolean willBeVisible = !a.mStartedActivity;
3457            if (!willBeVisible) {
3458                try {
3459                    willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
3460                            a.getActivityToken());
3461                } catch (RemoteException e) {
3462                    throw e.rethrowFromSystemServer();
3463                }
3464            }
3465            if (r.window == null && !a.mFinished && willBeVisible) {
3466                r.window = r.activity.getWindow();
3467                View decor = r.window.getDecorView();
3468                decor.setVisibility(View.INVISIBLE);
3469                ViewManager wm = a.getWindowManager();
3470                WindowManager.LayoutParams l = r.window.getAttributes();
3471                a.mDecor = decor;
3472                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
3473                l.softInputMode |= forwardBit;
3474                if (r.mPreserveWindow) {
3475                    a.mWindowAdded = true;
3476                    r.mPreserveWindow = false;
3477                    // Normally the ViewRoot sets up callbacks with the Activity
3478                    // in addView->ViewRootImpl#setView. If we are instead reusing
3479                    // the decor view we have to notify the view root that the
3480                    // callbacks may have changed.
3481                    ViewRootImpl impl = decor.getViewRootImpl();
3482                    if (impl != null) {
3483                        impl.notifyChildRebuilt();
3484                    }
3485                }
3486                if (a.mVisibleFromClient && !a.mWindowAdded) {
3487                    a.mWindowAdded = true;
3488                    wm.addView(decor, l);
3489                }
3490
3491            // If the window has already been added, but during resume
3492            // we started another activity, then don't yet make the
3493            // window visible.
3494            } else if (!willBeVisible) {
3495                if (localLOGV) Slog.v(
3496                    TAG, "Launch " + r + " mStartedActivity set");
3497                r.hideForNow = true;
3498            }
3499
3500            // Get rid of anything left hanging around.
3501            cleanUpPendingRemoveWindows(r, false /* force */);
3502
3503            // The window is now visible if it has been added, we are not
3504            // simply finishing, and we are not starting another activity.
3505            if (!r.activity.mFinished && willBeVisible
3506                    && r.activity.mDecor != null && !r.hideForNow) {
3507                if (r.newConfig != null) {
3508                    performConfigurationChangedForActivity(r, r.newConfig, REPORT_TO_ACTIVITY);
3509                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
3510                            + r.activityInfo.name + " with newConfig " + r.activity.mCurrentConfig);
3511                    r.newConfig = null;
3512                }
3513                if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
3514                        + isForward);
3515                WindowManager.LayoutParams l = r.window.getAttributes();
3516                if ((l.softInputMode
3517                        & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
3518                        != forwardBit) {
3519                    l.softInputMode = (l.softInputMode
3520                            & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
3521                            | forwardBit;
3522                    if (r.activity.mVisibleFromClient) {
3523                        ViewManager wm = a.getWindowManager();
3524                        View decor = r.window.getDecorView();
3525                        wm.updateViewLayout(decor, l);
3526                    }
3527                }
3528                r.activity.mVisibleFromServer = true;
3529                mNumVisibleActivities++;
3530                if (r.activity.mVisibleFromClient) {
3531                    r.activity.makeVisible();
3532                }
3533            }
3534
3535            if (!r.onlyLocalRequest) {
3536                r.nextIdle = mNewActivities;
3537                mNewActivities = r;
3538                if (localLOGV) Slog.v(
3539                    TAG, "Scheduling idle handler for " + r);
3540                Looper.myQueue().addIdleHandler(new Idler());
3541            }
3542            r.onlyLocalRequest = false;
3543
3544            // Tell the activity manager we have resumed.
3545            if (reallyResume) {
3546                try {
3547                    ActivityManagerNative.getDefault().activityResumed(token);
3548                } catch (RemoteException ex) {
3549                    throw ex.rethrowFromSystemServer();
3550                }
3551            }
3552
3553        } else {
3554            // If an exception was thrown when trying to resume, then
3555            // just end this activity.
3556            try {
3557                ActivityManagerNative.getDefault()
3558                    .finishActivity(token, Activity.RESULT_CANCELED, null,
3559                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
3560            } catch (RemoteException ex) {
3561                throw ex.rethrowFromSystemServer();
3562            }
3563        }
3564    }
3565
3566    private int mThumbnailWidth = -1;
3567    private int mThumbnailHeight = -1;
3568    private Bitmap mAvailThumbnailBitmap = null;
3569    private Canvas mThumbnailCanvas = null;
3570
3571    private Bitmap createThumbnailBitmap(ActivityClientRecord r) {
3572        Bitmap thumbnail = mAvailThumbnailBitmap;
3573        try {
3574            if (thumbnail == null) {
3575                int w = mThumbnailWidth;
3576                int h;
3577                if (w < 0) {
3578                    Resources res = r.activity.getResources();
3579                    int wId = com.android.internal.R.dimen.thumbnail_width;
3580                    int hId = com.android.internal.R.dimen.thumbnail_height;
3581                    mThumbnailWidth = w = res.getDimensionPixelSize(wId);
3582                    mThumbnailHeight = h = res.getDimensionPixelSize(hId);
3583                } else {
3584                    h = mThumbnailHeight;
3585                }
3586
3587                // On platforms where we don't want thumbnails, set dims to (0,0)
3588                if ((w > 0) && (h > 0)) {
3589                    thumbnail = Bitmap.createBitmap(r.activity.getResources().getDisplayMetrics(),
3590                            w, h, THUMBNAIL_FORMAT);
3591                    thumbnail.eraseColor(0);
3592                }
3593            }
3594
3595            if (thumbnail != null) {
3596                Canvas cv = mThumbnailCanvas;
3597                if (cv == null) {
3598                    mThumbnailCanvas = cv = new Canvas();
3599                }
3600
3601                cv.setBitmap(thumbnail);
3602                if (!r.activity.onCreateThumbnail(thumbnail, cv)) {
3603                    mAvailThumbnailBitmap = thumbnail;
3604                    thumbnail = null;
3605                }
3606                cv.setBitmap(null);
3607            }
3608
3609        } catch (Exception e) {
3610            if (!mInstrumentation.onException(r.activity, e)) {
3611                throw new RuntimeException(
3612                        "Unable to create thumbnail of "
3613                        + r.intent.getComponent().toShortString()
3614                        + ": " + e.toString(), e);
3615            }
3616            thumbnail = null;
3617        }
3618
3619        return thumbnail;
3620    }
3621
3622    private void handlePauseActivity(IBinder token, boolean finished,
3623            boolean userLeaving, int configChanges, boolean dontReport, int seq) {
3624        ActivityClientRecord r = mActivities.get(token);
3625        if (DEBUG_ORDER) Slog.d(TAG, "handlePauseActivity " + r + ", seq: " + seq);
3626        if (!checkAndUpdateLifecycleSeq(seq, r, "pauseActivity")) {
3627            return;
3628        }
3629        if (r != null) {
3630            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
3631            if (userLeaving) {
3632                performUserLeavingActivity(r);
3633            }
3634
3635            r.activity.mConfigChangeFlags |= configChanges;
3636            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
3637
3638            // Make sure any pending writes are now committed.
3639            if (r.isPreHoneycomb()) {
3640                QueuedWork.waitToFinish();
3641            }
3642
3643            // Tell the activity manager we have paused.
3644            if (!dontReport) {
3645                try {
3646                    ActivityManagerNative.getDefault().activityPaused(token);
3647                } catch (RemoteException ex) {
3648                    throw ex.rethrowFromSystemServer();
3649                }
3650            }
3651            mSomeActivitiesChanged = true;
3652        }
3653    }
3654
3655    final void performUserLeavingActivity(ActivityClientRecord r) {
3656        mInstrumentation.callActivityOnUserLeaving(r.activity);
3657    }
3658
3659    final Bundle performPauseActivity(IBinder token, boolean finished,
3660            boolean saveState, String reason) {
3661        ActivityClientRecord r = mActivities.get(token);
3662        return r != null ? performPauseActivity(r, finished, saveState, reason) : null;
3663    }
3664
3665    final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
3666            boolean saveState, String reason) {
3667        if (r.paused) {
3668            if (r.activity.mFinished) {
3669                // If we are finishing, we won't call onResume() in certain cases.
3670                // So here we likewise don't want to call onPause() if the activity
3671                // isn't resumed.
3672                return null;
3673            }
3674            RuntimeException e = new RuntimeException(
3675                    "Performing pause of activity that is not resumed: "
3676                    + r.intent.getComponent().toShortString());
3677            Slog.e(TAG, e.getMessage(), e);
3678        }
3679        if (finished) {
3680            r.activity.mFinished = true;
3681        }
3682
3683        // Next have the activity save its current state and managed dialogs...
3684        if (!r.activity.mFinished && saveState) {
3685            callCallActivityOnSaveInstanceState(r);
3686        }
3687
3688        performPauseActivityIfNeeded(r, reason);
3689
3690        // Notify any outstanding on paused listeners
3691        ArrayList<OnActivityPausedListener> listeners;
3692        synchronized (mOnPauseListeners) {
3693            listeners = mOnPauseListeners.remove(r.activity);
3694        }
3695        int size = (listeners != null ? listeners.size() : 0);
3696        for (int i = 0; i < size; i++) {
3697            listeners.get(i).onPaused(r.activity);
3698        }
3699
3700        return !r.activity.mFinished && saveState ? r.state : null;
3701    }
3702
3703    private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
3704        if (r.paused) {
3705            // You are already paused silly...
3706            return;
3707        }
3708
3709        try {
3710            r.activity.mCalled = false;
3711            mInstrumentation.callActivityOnPause(r.activity);
3712            EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
3713                    r.activity.getComponentName().getClassName(), reason);
3714            if (!r.activity.mCalled) {
3715                throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent)
3716                        + " did not call through to super.onPause()");
3717            }
3718        } catch (SuperNotCalledException e) {
3719            throw e;
3720        } catch (Exception e) {
3721            if (!mInstrumentation.onException(r.activity, e)) {
3722                throw new RuntimeException("Unable to pause activity "
3723                        + safeToComponentShortString(r.intent) + ": " + e.toString(), e);
3724            }
3725        }
3726        r.paused = true;
3727    }
3728
3729    final void performStopActivity(IBinder token, boolean saveState, String reason) {
3730        ActivityClientRecord r = mActivities.get(token);
3731        performStopActivityInner(r, null, false, saveState, reason);
3732    }
3733
3734    private static class StopInfo implements Runnable {
3735        ActivityClientRecord activity;
3736        Bundle state;
3737        PersistableBundle persistentState;
3738        CharSequence description;
3739
3740        @Override public void run() {
3741            // Tell activity manager we have been stopped.
3742            try {
3743                if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Reporting activity stopped: " + activity);
3744                ActivityManagerNative.getDefault().activityStopped(
3745                    activity.token, state, persistentState, description);
3746            } catch (RemoteException ex) {
3747                if (ex instanceof TransactionTooLargeException
3748                        && activity.packageInfo.getTargetSdkVersion() < Build.VERSION_CODES.N) {
3749                    Log.e(TAG, "App sent too much data in instance state, so it was ignored", ex);
3750                    return;
3751                }
3752                throw ex.rethrowFromSystemServer();
3753            }
3754        }
3755    }
3756
3757    private static final class ProviderRefCount {
3758        public final IActivityManager.ContentProviderHolder holder;
3759        public final ProviderClientRecord client;
3760        public int stableCount;
3761        public int unstableCount;
3762
3763        // When this is set, the stable and unstable ref counts are 0 and
3764        // we have a pending operation scheduled to remove the ref count
3765        // from the activity manager.  On the activity manager we are still
3766        // holding an unstable ref, though it is not reflected in the counts
3767        // here.
3768        public boolean removePending;
3769
3770        ProviderRefCount(IActivityManager.ContentProviderHolder inHolder,
3771                ProviderClientRecord inClient, int sCount, int uCount) {
3772            holder = inHolder;
3773            client = inClient;
3774            stableCount = sCount;
3775            unstableCount = uCount;
3776        }
3777    }
3778
3779    /**
3780     * Core implementation of stopping an activity.  Note this is a little
3781     * tricky because the server's meaning of stop is slightly different
3782     * than our client -- for the server, stop means to save state and give
3783     * it the result when it is done, but the window may still be visible.
3784     * For the client, we want to call onStop()/onStart() to indicate when
3785     * the activity's UI visibillity changes.
3786     */
3787    private void performStopActivityInner(ActivityClientRecord r,
3788            StopInfo info, boolean keepShown, boolean saveState, String reason) {
3789        if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
3790        if (r != null) {
3791            if (!keepShown && r.stopped) {
3792                if (r.activity.mFinished) {
3793                    // If we are finishing, we won't call onResume() in certain
3794                    // cases.  So here we likewise don't want to call onStop()
3795                    // if the activity isn't resumed.
3796                    return;
3797                }
3798                RuntimeException e = new RuntimeException(
3799                        "Performing stop of activity that is already stopped: "
3800                        + r.intent.getComponent().toShortString());
3801                Slog.e(TAG, e.getMessage(), e);
3802                Slog.e(TAG, r.getStateString());
3803            }
3804
3805            // One must first be paused before stopped...
3806            performPauseActivityIfNeeded(r, reason);
3807
3808            if (info != null) {
3809                try {
3810                    // First create a thumbnail for the activity...
3811                    // For now, don't create the thumbnail here; we are
3812                    // doing that by doing a screen snapshot.
3813                    info.description = r.activity.onCreateDescription();
3814                } catch (Exception e) {
3815                    if (!mInstrumentation.onException(r.activity, e)) {
3816                        throw new RuntimeException(
3817                                "Unable to save state of activity "
3818                                + r.intent.getComponent().toShortString()
3819                                + ": " + e.toString(), e);
3820                    }
3821                }
3822            }
3823
3824            // Next have the activity save its current state and managed dialogs...
3825            if (!r.activity.mFinished && saveState) {
3826                if (r.state == null) {
3827                    callCallActivityOnSaveInstanceState(r);
3828                }
3829            }
3830
3831            if (!keepShown) {
3832                try {
3833                    // Now we are idle.
3834                    r.activity.performStop(false /*preserveWindow*/);
3835                } catch (Exception e) {
3836                    if (!mInstrumentation.onException(r.activity, e)) {
3837                        throw new RuntimeException(
3838                                "Unable to stop activity "
3839                                + r.intent.getComponent().toShortString()
3840                                + ": " + e.toString(), e);
3841                    }
3842                }
3843                r.stopped = true;
3844                EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(),
3845                        r.activity.getComponentName().getClassName(), reason);
3846            }
3847        }
3848    }
3849
3850    private void updateVisibility(ActivityClientRecord r, boolean show) {
3851        View v = r.activity.mDecor;
3852        if (v != null) {
3853            if (show) {
3854                if (!r.activity.mVisibleFromServer) {
3855                    r.activity.mVisibleFromServer = true;
3856                    mNumVisibleActivities++;
3857                    if (r.activity.mVisibleFromClient) {
3858                        r.activity.makeVisible();
3859                    }
3860                }
3861                if (r.newConfig != null) {
3862                    performConfigurationChangedForActivity(r, r.newConfig, REPORT_TO_ACTIVITY);
3863                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
3864                            + r.activityInfo.name + " with new config "
3865                            + r.activity.mCurrentConfig);
3866                    r.newConfig = null;
3867                }
3868            } else {
3869                if (r.activity.mVisibleFromServer) {
3870                    r.activity.mVisibleFromServer = false;
3871                    mNumVisibleActivities--;
3872                    v.setVisibility(View.INVISIBLE);
3873                }
3874            }
3875        }
3876    }
3877
3878    private void handleStopActivity(IBinder token, boolean show, int configChanges, int seq) {
3879        ActivityClientRecord r = mActivities.get(token);
3880        if (!checkAndUpdateLifecycleSeq(seq, r, "stopActivity")) {
3881            return;
3882        }
3883        r.activity.mConfigChangeFlags |= configChanges;
3884
3885        StopInfo info = new StopInfo();
3886        performStopActivityInner(r, info, show, true, "handleStopActivity");
3887
3888        if (localLOGV) Slog.v(
3889            TAG, "Finishing stop of " + r + ": show=" + show
3890            + " win=" + r.window);
3891
3892        updateVisibility(r, show);
3893
3894        // Make sure any pending writes are now committed.
3895        if (!r.isPreHoneycomb()) {
3896            QueuedWork.waitToFinish();
3897        }
3898
3899        // Schedule the call to tell the activity manager we have
3900        // stopped.  We don't do this immediately, because we want to
3901        // have a chance for any other pending work (in particular memory
3902        // trim requests) to complete before you tell the activity
3903        // manager to proceed and allow us to go fully into the background.
3904        info.activity = r;
3905        info.state = r.state;
3906        info.persistentState = r.persistentState;
3907        mH.post(info);
3908        mSomeActivitiesChanged = true;
3909    }
3910
3911    private static boolean checkAndUpdateLifecycleSeq(int seq, ActivityClientRecord r,
3912            String action) {
3913        if (r == null) {
3914            return true;
3915        }
3916        if (seq < r.lastProcessedSeq) {
3917            if (DEBUG_ORDER) Slog.d(TAG, action + " for " + r + " ignored, because seq=" + seq
3918                    + " < mCurrentLifecycleSeq=" + r.lastProcessedSeq);
3919            return false;
3920        }
3921        r.lastProcessedSeq = seq;
3922        return true;
3923    }
3924
3925    final void performRestartActivity(IBinder token) {
3926        ActivityClientRecord r = mActivities.get(token);
3927        if (r.stopped) {
3928            r.activity.performRestart();
3929            r.stopped = false;
3930        }
3931    }
3932
3933    private void handleWindowVisibility(IBinder token, boolean show) {
3934        ActivityClientRecord r = mActivities.get(token);
3935
3936        if (r == null) {
3937            Log.w(TAG, "handleWindowVisibility: no activity for token " + token);
3938            return;
3939        }
3940
3941        if (!show && !r.stopped) {
3942            performStopActivityInner(r, null, show, false, "handleWindowVisibility");
3943        } else if (show && r.stopped) {
3944            // If we are getting ready to gc after going to the background, well
3945            // we are back active so skip it.
3946            unscheduleGcIdler();
3947
3948            r.activity.performRestart();
3949            r.stopped = false;
3950        }
3951        if (r.activity.mDecor != null) {
3952            if (false) Slog.v(
3953                TAG, "Handle window " + r + " visibility: " + show);
3954            updateVisibility(r, show);
3955        }
3956        mSomeActivitiesChanged = true;
3957    }
3958
3959    private void handleSleeping(IBinder token, boolean sleeping) {
3960        ActivityClientRecord r = mActivities.get(token);
3961
3962        if (r == null) {
3963            Log.w(TAG, "handleSleeping: no activity for token " + token);
3964            return;
3965        }
3966
3967        if (sleeping) {
3968            if (!r.stopped && !r.isPreHoneycomb()) {
3969                try {
3970                    // Now we are idle.
3971                    r.activity.performStop(false /*preserveWindow*/);
3972                } catch (Exception e) {
3973                    if (!mInstrumentation.onException(r.activity, e)) {
3974                        throw new RuntimeException(
3975                                "Unable to stop activity "
3976                                + r.intent.getComponent().toShortString()
3977                                + ": " + e.toString(), e);
3978                    }
3979                }
3980                r.stopped = true;
3981                EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(),
3982                        r.activity.getComponentName().getClassName(), "sleeping");
3983            }
3984
3985            // Make sure any pending writes are now committed.
3986            if (!r.isPreHoneycomb()) {
3987                QueuedWork.waitToFinish();
3988            }
3989
3990            // Tell activity manager we slept.
3991            try {
3992                ActivityManagerNative.getDefault().activitySlept(r.token);
3993            } catch (RemoteException ex) {
3994                throw ex.rethrowFromSystemServer();
3995            }
3996        } else {
3997            if (r.stopped && r.activity.mVisibleFromServer) {
3998                r.activity.performRestart();
3999                r.stopped = false;
4000            }
4001        }
4002    }
4003
4004    private void handleSetCoreSettings(Bundle coreSettings) {
4005        synchronized (mResourcesManager) {
4006            mCoreSettings = coreSettings;
4007        }
4008        onCoreSettingsChange();
4009    }
4010
4011    private void onCoreSettingsChange() {
4012        boolean debugViewAttributes =
4013                mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;
4014        if (debugViewAttributes != View.mDebugViewAttributes) {
4015            View.mDebugViewAttributes = debugViewAttributes;
4016
4017            // request all activities to relaunch for the changes to take place
4018            for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) {
4019                requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, null, false,
4020                        false /* preserveWindow */);
4021            }
4022        }
4023    }
4024
4025    private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) {
4026        LoadedApk apk = peekPackageInfo(data.pkg, false);
4027        if (apk != null) {
4028            apk.setCompatibilityInfo(data.info);
4029        }
4030        apk = peekPackageInfo(data.pkg, true);
4031        if (apk != null) {
4032            apk.setCompatibilityInfo(data.info);
4033        }
4034        handleConfigurationChanged(mConfiguration, data.info);
4035        WindowManagerGlobal.getInstance().reportNewConfiguration(mConfiguration);
4036    }
4037
4038    private void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
4039        final int N = results.size();
4040        for (int i=0; i<N; i++) {
4041            ResultInfo ri = results.get(i);
4042            try {
4043                if (ri.mData != null) {
4044                    ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
4045                    ri.mData.prepareToEnterProcess();
4046                }
4047                if (DEBUG_RESULTS) Slog.v(TAG,
4048                        "Delivering result to activity " + r + " : " + ri);
4049                r.activity.dispatchActivityResult(ri.mResultWho,
4050                        ri.mRequestCode, ri.mResultCode, ri.mData);
4051            } catch (Exception e) {
4052                if (!mInstrumentation.onException(r.activity, e)) {
4053                    throw new RuntimeException(
4054                            "Failure delivering result " + ri + " to activity "
4055                            + r.intent.getComponent().toShortString()
4056                            + ": " + e.toString(), e);
4057                }
4058            }
4059        }
4060    }
4061
4062    private void handleSendResult(ResultData res) {
4063        ActivityClientRecord r = mActivities.get(res.token);
4064        if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
4065        if (r != null) {
4066            final boolean resumed = !r.paused;
4067            if (!r.activity.mFinished && r.activity.mDecor != null
4068                    && r.hideForNow && resumed) {
4069                // We had hidden the activity because it started another
4070                // one...  we have gotten a result back and we are not
4071                // paused, so make sure our window is visible.
4072                updateVisibility(r, true);
4073            }
4074            if (resumed) {
4075                try {
4076                    // Now we are idle.
4077                    r.activity.mCalled = false;
4078                    r.activity.mTemporaryPause = true;
4079                    mInstrumentation.callActivityOnPause(r.activity);
4080                    if (!r.activity.mCalled) {
4081                        throw new SuperNotCalledException(
4082                            "Activity " + r.intent.getComponent().toShortString()
4083                            + " did not call through to super.onPause()");
4084                    }
4085                } catch (SuperNotCalledException e) {
4086                    throw e;
4087                } catch (Exception e) {
4088                    if (!mInstrumentation.onException(r.activity, e)) {
4089                        throw new RuntimeException(
4090                                "Unable to pause activity "
4091                                + r.intent.getComponent().toShortString()
4092                                + ": " + e.toString(), e);
4093                    }
4094                }
4095            }
4096            deliverResults(r, res.results);
4097            if (resumed) {
4098                r.activity.performResume();
4099                r.activity.mTemporaryPause = false;
4100            }
4101        }
4102    }
4103
4104    public final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing) {
4105        return performDestroyActivity(token, finishing, 0, false);
4106    }
4107
4108    private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
4109            int configChanges, boolean getNonConfigInstance) {
4110        ActivityClientRecord r = mActivities.get(token);
4111        Class<? extends Activity> activityClass = null;
4112        if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
4113        if (r != null) {
4114            activityClass = r.activity.getClass();
4115            r.activity.mConfigChangeFlags |= configChanges;
4116            if (finishing) {
4117                r.activity.mFinished = true;
4118            }
4119
4120            performPauseActivityIfNeeded(r, "destroy");
4121
4122            if (!r.stopped) {
4123                try {
4124                    r.activity.performStop(r.mPreserveWindow);
4125                } catch (SuperNotCalledException e) {
4126                    throw e;
4127                } catch (Exception e) {
4128                    if (!mInstrumentation.onException(r.activity, e)) {
4129                        throw new RuntimeException(
4130                                "Unable to stop activity "
4131                                + safeToComponentShortString(r.intent)
4132                                + ": " + e.toString(), e);
4133                    }
4134                }
4135                r.stopped = true;
4136                EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(),
4137                        r.activity.getComponentName().getClassName(), "destroy");
4138            }
4139            if (getNonConfigInstance) {
4140                try {
4141                    r.lastNonConfigurationInstances
4142                            = r.activity.retainNonConfigurationInstances();
4143                } catch (Exception e) {
4144                    if (!mInstrumentation.onException(r.activity, e)) {
4145                        throw new RuntimeException(
4146                                "Unable to retain activity "
4147                                + r.intent.getComponent().toShortString()
4148                                + ": " + e.toString(), e);
4149                    }
4150                }
4151            }
4152            try {
4153                r.activity.mCalled = false;
4154                mInstrumentation.callActivityOnDestroy(r.activity);
4155                if (!r.activity.mCalled) {
4156                    throw new SuperNotCalledException(
4157                        "Activity " + safeToComponentShortString(r.intent) +
4158                        " did not call through to super.onDestroy()");
4159                }
4160                if (r.window != null) {
4161                    r.window.closeAllPanels();
4162                }
4163            } catch (SuperNotCalledException e) {
4164                throw e;
4165            } catch (Exception e) {
4166                if (!mInstrumentation.onException(r.activity, e)) {
4167                    throw new RuntimeException(
4168                            "Unable to destroy activity " + safeToComponentShortString(r.intent)
4169                            + ": " + e.toString(), e);
4170                }
4171            }
4172        }
4173        mActivities.remove(token);
4174        StrictMode.decrementExpectedActivityCount(activityClass);
4175        return r;
4176    }
4177
4178    private static String safeToComponentShortString(Intent intent) {
4179        ComponentName component = intent.getComponent();
4180        return component == null ? "[Unknown]" : component.toShortString();
4181    }
4182
4183    private void handleDestroyActivity(IBinder token, boolean finishing,
4184            int configChanges, boolean getNonConfigInstance) {
4185        ActivityClientRecord r = performDestroyActivity(token, finishing,
4186                configChanges, getNonConfigInstance);
4187        if (r != null) {
4188            cleanUpPendingRemoveWindows(r, finishing);
4189            WindowManager wm = r.activity.getWindowManager();
4190            View v = r.activity.mDecor;
4191            if (v != null) {
4192                if (r.activity.mVisibleFromServer) {
4193                    mNumVisibleActivities--;
4194                }
4195                IBinder wtoken = v.getWindowToken();
4196                if (r.activity.mWindowAdded) {
4197                    if (r.mPreserveWindow) {
4198                        // Hold off on removing this until the new activity's
4199                        // window is being added.
4200                        r.mPendingRemoveWindow = r.window;
4201                        r.mPendingRemoveWindowManager = wm;
4202                        // We can only keep the part of the view hierarchy that we control,
4203                        // everything else must be removed, because it might not be able to
4204                        // behave properly when activity is relaunching.
4205                        r.window.clearContentView();
4206                    } else {
4207                        wm.removeViewImmediate(v);
4208                    }
4209                }
4210                if (wtoken != null && r.mPendingRemoveWindow == null) {
4211                    WindowManagerGlobal.getInstance().closeAll(wtoken,
4212                            r.activity.getClass().getName(), "Activity");
4213                } else if (r.mPendingRemoveWindow != null) {
4214                    // We're preserving only one window, others should be closed so app views
4215                    // will be detached before the final tear down. It should be done now because
4216                    // some components (e.g. WebView) rely on detach callbacks to perform receiver
4217                    // unregister and other cleanup.
4218                    WindowManagerGlobal.getInstance().closeAllExceptView(token, v,
4219                            r.activity.getClass().getName(), "Activity");
4220                }
4221                r.activity.mDecor = null;
4222            }
4223            if (r.mPendingRemoveWindow == null) {
4224                // If we are delaying the removal of the activity window, then
4225                // we can't clean up all windows here.  Note that we can't do
4226                // so later either, which means any windows that aren't closed
4227                // by the app will leak.  Well we try to warning them a lot
4228                // about leaking windows, because that is a bug, so if they are
4229                // using this recreate facility then they get to live with leaks.
4230                WindowManagerGlobal.getInstance().closeAll(token,
4231                        r.activity.getClass().getName(), "Activity");
4232            }
4233
4234            // Mocked out contexts won't be participating in the normal
4235            // process lifecycle, but if we're running with a proper
4236            // ApplicationContext we need to have it tear down things
4237            // cleanly.
4238            Context c = r.activity.getBaseContext();
4239            if (c instanceof ContextImpl) {
4240                ((ContextImpl) c).scheduleFinalCleanup(
4241                        r.activity.getClass().getName(), "Activity");
4242            }
4243        }
4244        if (finishing) {
4245            try {
4246                ActivityManagerNative.getDefault().activityDestroyed(token);
4247            } catch (RemoteException ex) {
4248                throw ex.rethrowFromSystemServer();
4249            }
4250        }
4251        mSomeActivitiesChanged = true;
4252    }
4253
4254    /**
4255     * @param preserveWindow Whether the activity should try to reuse the window it created,
4256     *                        including the decor view after the relaunch.
4257     */
4258    public final void requestRelaunchActivity(IBinder token,
4259            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
4260            int configChanges, boolean notResumed, Configuration config,
4261            Configuration overrideConfig, boolean fromServer, boolean preserveWindow) {
4262        ActivityClientRecord target = null;
4263
4264        synchronized (mResourcesManager) {
4265            for (int i=0; i<mRelaunchingActivities.size(); i++) {
4266                ActivityClientRecord r = mRelaunchingActivities.get(i);
4267                if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: " + this + ", trying: " + r);
4268                if (r.token == token) {
4269                    target = r;
4270                    if (pendingResults != null) {
4271                        if (r.pendingResults != null) {
4272                            r.pendingResults.addAll(pendingResults);
4273                        } else {
4274                            r.pendingResults = pendingResults;
4275                        }
4276                    }
4277                    if (pendingNewIntents != null) {
4278                        if (r.pendingIntents != null) {
4279                            r.pendingIntents.addAll(pendingNewIntents);
4280                        } else {
4281                            r.pendingIntents = pendingNewIntents;
4282                        }
4283                    }
4284
4285                    // For each relaunch request, activity manager expects an answer
4286                    if (!r.onlyLocalRequest && fromServer) {
4287                        try {
4288                            ActivityManagerNative.getDefault().activityRelaunched(token);
4289                        } catch (RemoteException e) {
4290                            throw e.rethrowFromSystemServer();
4291                        }
4292                    }
4293                    break;
4294                }
4295            }
4296
4297            if (target == null) {
4298                if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: target is null, fromServer:"
4299                        + fromServer);
4300                target = new ActivityClientRecord();
4301                target.token = token;
4302                target.pendingResults = pendingResults;
4303                target.pendingIntents = pendingNewIntents;
4304                target.mPreserveWindow = preserveWindow;
4305                if (!fromServer) {
4306                    final ActivityClientRecord existing = mActivities.get(token);
4307                    if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: " + existing);
4308                    if (existing != null) {
4309                        if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: paused= "
4310                                + existing.paused);;
4311                        target.startsNotResumed = existing.paused;
4312                        target.overrideConfig = existing.overrideConfig;
4313                    }
4314                    target.onlyLocalRequest = true;
4315                }
4316                mRelaunchingActivities.add(target);
4317                sendMessage(H.RELAUNCH_ACTIVITY, target);
4318            }
4319
4320            if (fromServer) {
4321                target.startsNotResumed = notResumed;
4322                target.onlyLocalRequest = false;
4323            }
4324            if (config != null) {
4325                target.createdConfig = config;
4326            }
4327            if (overrideConfig != null) {
4328                target.overrideConfig = overrideConfig;
4329            }
4330            target.pendingConfigChanges |= configChanges;
4331            target.relaunchSeq = getLifecycleSeq();
4332        }
4333        if (DEBUG_ORDER) Slog.d(TAG, "relaunchActivity " + ActivityThread.this + ", target "
4334                + target + " operation received seq: " + target.relaunchSeq);
4335    }
4336
4337    private void handleRelaunchActivity(ActivityClientRecord tmp) {
4338        // If we are getting ready to gc after going to the background, well
4339        // we are back active so skip it.
4340        unscheduleGcIdler();
4341        mSomeActivitiesChanged = true;
4342
4343        Configuration changedConfig = null;
4344        int configChanges = 0;
4345
4346        // First: make sure we have the most recent configuration and most
4347        // recent version of the activity, or skip it if some previous call
4348        // had taken a more recent version.
4349        synchronized (mResourcesManager) {
4350            int N = mRelaunchingActivities.size();
4351            IBinder token = tmp.token;
4352            tmp = null;
4353            for (int i=0; i<N; i++) {
4354                ActivityClientRecord r = mRelaunchingActivities.get(i);
4355                if (r.token == token) {
4356                    tmp = r;
4357                    configChanges |= tmp.pendingConfigChanges;
4358                    mRelaunchingActivities.remove(i);
4359                    i--;
4360                    N--;
4361                }
4362            }
4363
4364            if (tmp == null) {
4365                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Abort, activity not relaunching!");
4366                return;
4367            }
4368
4369            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
4370                    + tmp.token + " with configChanges=0x"
4371                    + Integer.toHexString(configChanges));
4372
4373            if (mPendingConfiguration != null) {
4374                changedConfig = mPendingConfiguration;
4375                mPendingConfiguration = null;
4376            }
4377        }
4378
4379        if (tmp.lastProcessedSeq > tmp.relaunchSeq) {
4380            Slog.wtf(TAG, "For some reason target: " + tmp + " has lower sequence: "
4381                    + tmp.relaunchSeq + " than current sequence: " + tmp.lastProcessedSeq);
4382        } else {
4383            tmp.lastProcessedSeq = tmp.relaunchSeq;
4384        }
4385        if (tmp.createdConfig != null) {
4386            // If the activity manager is passing us its current config,
4387            // assume that is really what we want regardless of what we
4388            // may have pending.
4389            if (mConfiguration == null
4390                    || (tmp.createdConfig.isOtherSeqNewer(mConfiguration)
4391                            && mConfiguration.diff(tmp.createdConfig) != 0)) {
4392                if (changedConfig == null
4393                        || tmp.createdConfig.isOtherSeqNewer(changedConfig)) {
4394                    changedConfig = tmp.createdConfig;
4395                }
4396            }
4397        }
4398
4399        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Relaunching activity "
4400                + tmp.token + ": changedConfig=" + changedConfig);
4401
4402        // If there was a pending configuration change, execute it first.
4403        if (changedConfig != null) {
4404            mCurDefaultDisplayDpi = changedConfig.densityDpi;
4405            updateDefaultDensity();
4406            handleConfigurationChanged(changedConfig, null);
4407        }
4408
4409        ActivityClientRecord r = mActivities.get(tmp.token);
4410        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r);
4411        if (r == null) {
4412            if (!tmp.onlyLocalRequest) {
4413                try {
4414                    ActivityManagerNative.getDefault().activityRelaunched(tmp.token);
4415                } catch (RemoteException e) {
4416                    throw e.rethrowFromSystemServer();
4417                }
4418            }
4419            return;
4420        }
4421
4422        r.activity.mConfigChangeFlags |= configChanges;
4423        r.onlyLocalRequest = tmp.onlyLocalRequest;
4424        r.mPreserveWindow = tmp.mPreserveWindow;
4425        r.lastProcessedSeq = tmp.lastProcessedSeq;
4426        r.relaunchSeq = tmp.relaunchSeq;
4427        Intent currentIntent = r.activity.mIntent;
4428
4429        r.activity.mChangingConfigurations = true;
4430
4431        // If we are preserving the main window across relaunches we would also like to preserve
4432        // the children. However the client side view system does not support preserving
4433        // the child views so we notify the window manager to expect these windows to
4434        // be replaced and defer requests to destroy or hide them. This way we can achieve
4435        // visual continuity. It's important that we do this here prior to pause and destroy
4436        // as that is when we may hide or remove the child views.
4437        //
4438        // There is another scenario, if we have decided locally to relaunch the app from a
4439        // call to recreate, then none of the windows will be prepared for replacement or
4440        // preserved by the server, so we want to notify it that we are preparing to replace
4441        // everything
4442        try {
4443            if (r.mPreserveWindow || r.onlyLocalRequest) {
4444                WindowManagerGlobal.getWindowSession().prepareToReplaceWindows(
4445                        r.token, !r.onlyLocalRequest);
4446            }
4447        } catch (RemoteException e) {
4448            throw e.rethrowFromSystemServer();
4449        }
4450
4451        // Need to ensure state is saved.
4452        if (!r.paused) {
4453            performPauseActivity(r.token, false, r.isPreHoneycomb(), "handleRelaunchActivity");
4454        }
4455        if (r.state == null && !r.stopped && !r.isPreHoneycomb()) {
4456            callCallActivityOnSaveInstanceState(r);
4457        }
4458
4459        handleDestroyActivity(r.token, false, configChanges, true);
4460
4461        r.activity = null;
4462        r.window = null;
4463        r.hideForNow = false;
4464        r.nextIdle = null;
4465        // Merge any pending results and pending intents; don't just replace them
4466        if (tmp.pendingResults != null) {
4467            if (r.pendingResults == null) {
4468                r.pendingResults = tmp.pendingResults;
4469            } else {
4470                r.pendingResults.addAll(tmp.pendingResults);
4471            }
4472        }
4473        if (tmp.pendingIntents != null) {
4474            if (r.pendingIntents == null) {
4475                r.pendingIntents = tmp.pendingIntents;
4476            } else {
4477                r.pendingIntents.addAll(tmp.pendingIntents);
4478            }
4479        }
4480        r.startsNotResumed = tmp.startsNotResumed;
4481        r.overrideConfig = tmp.overrideConfig;
4482
4483        handleLaunchActivity(r, currentIntent, "handleRelaunchActivity");
4484
4485        if (!tmp.onlyLocalRequest) {
4486            try {
4487                ActivityManagerNative.getDefault().activityRelaunched(r.token);
4488                if (r.window != null) {
4489                    r.window.reportActivityRelaunched();
4490                }
4491            } catch (RemoteException e) {
4492                throw e.rethrowFromSystemServer();
4493            }
4494        }
4495    }
4496
4497    private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) {
4498        r.state = new Bundle();
4499        r.state.setAllowFds(false);
4500        if (r.isPersistable()) {
4501            r.persistentState = new PersistableBundle();
4502            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state,
4503                    r.persistentState);
4504        } else {
4505            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
4506        }
4507    }
4508
4509    ArrayList<ComponentCallbacks2> collectComponentCallbacks(
4510            boolean allActivities, Configuration newConfig) {
4511        ArrayList<ComponentCallbacks2> callbacks
4512                = new ArrayList<ComponentCallbacks2>();
4513
4514        synchronized (mResourcesManager) {
4515            final int NAPP = mAllApplications.size();
4516            for (int i=0; i<NAPP; i++) {
4517                callbacks.add(mAllApplications.get(i));
4518            }
4519            final int NACT = mActivities.size();
4520            for (int i=0; i<NACT; i++) {
4521                ActivityClientRecord ar = mActivities.valueAt(i);
4522                Activity a = ar.activity;
4523                if (a != null) {
4524                    Configuration thisConfig = applyConfigCompatMainThread(
4525                            mCurDefaultDisplayDpi, newConfig,
4526                            ar.packageInfo.getCompatibilityInfo());
4527                    if (!ar.activity.mFinished && (allActivities || !ar.paused)) {
4528                        // If the activity is currently resumed, its configuration
4529                        // needs to change right now.
4530                        callbacks.add(a);
4531                    } else if (thisConfig != null) {
4532                        // Otherwise, we will tell it about the change
4533                        // the next time it is resumed or shown.  Note that
4534                        // the activity manager may, before then, decide the
4535                        // activity needs to be destroyed to handle its new
4536                        // configuration.
4537                        if (DEBUG_CONFIGURATION) {
4538                            Slog.v(TAG, "Setting activity "
4539                                    + ar.activityInfo.name + " newConfig=" + thisConfig);
4540                        }
4541                        ar.newConfig = thisConfig;
4542                    }
4543                }
4544            }
4545            final int NSVC = mServices.size();
4546            for (int i=0; i<NSVC; i++) {
4547                callbacks.add(mServices.valueAt(i));
4548            }
4549        }
4550        synchronized (mProviderMap) {
4551            final int NPRV = mLocalProviders.size();
4552            for (int i=0; i<NPRV; i++) {
4553                callbacks.add(mLocalProviders.valueAt(i).mLocalProvider);
4554            }
4555        }
4556
4557        return callbacks;
4558    }
4559
4560    /**
4561     * Updates the configuration for an Activity. The ActivityClientRecord's
4562     * {@link ActivityClientRecord#overrideConfig} is used to compute the final Configuration for
4563     * that Activity. {@link ActivityClientRecord#tmpConfig} is used as a temporary for delivering
4564     * the updated Configuration.
4565     * @param r ActivityClientRecord representing the Activity.
4566     * @param newBaseConfig The new configuration to use. This may be augmented with
4567     *                      {@link ActivityClientRecord#overrideConfig}.
4568     * @param reportToActivity true if the change should be reported to the Activity's callback.
4569     */
4570    private void performConfigurationChangedForActivity(ActivityClientRecord r,
4571                                                        Configuration newBaseConfig,
4572                                                        boolean reportToActivity) {
4573        r.tmpConfig.setTo(newBaseConfig);
4574        if (r.overrideConfig != null) {
4575            r.tmpConfig.updateFrom(r.overrideConfig);
4576        }
4577        performConfigurationChanged(r.activity, r.token, r.tmpConfig, r.overrideConfig,
4578                reportToActivity);
4579        freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.tmpConfig));
4580    }
4581
4582    /**
4583     * Creates a new Configuration only if override would modify base. Otherwise returns base.
4584     * @param base The base configuration.
4585     * @param override The update to apply to the base configuration. Can be null.
4586     * @return A Configuration representing base with override applied.
4587     */
4588    private static Configuration createNewConfigAndUpdateIfNotNull(@NonNull Configuration base,
4589            @Nullable Configuration override) {
4590        if (override == null) {
4591            return base;
4592        }
4593        Configuration newConfig = new Configuration(base);
4594        newConfig.updateFrom(override);
4595        return newConfig;
4596    }
4597
4598    /**
4599     * Decides whether to update an Activity's configuration and whether to tell the
4600     * Activity/Component about it.
4601     * @param cb The component callback to notify of configuration change.
4602     * @param activityToken The Activity binder token for which this configuration change happened.
4603     *                      If the change is global, this is null.
4604     * @param newConfig The new configuration.
4605     * @param amOverrideConfig The override config that differentiates the Activity's configuration
4606     *                       from the base global configuration.
4607     *                       This is supplied by ActivityManager.
4608     * @param reportToActivity Notify the Activity of the change.
4609     */
4610    private void performConfigurationChanged(ComponentCallbacks2 cb,
4611                                             IBinder activityToken,
4612                                             Configuration newConfig,
4613                                             Configuration amOverrideConfig,
4614                                             boolean reportToActivity) {
4615        // Only for Activity objects, check that they actually call up to their
4616        // superclass implementation.  ComponentCallbacks2 is an interface, so
4617        // we check the runtime type and act accordingly.
4618        Activity activity = (cb instanceof Activity) ? (Activity) cb : null;
4619        if (activity != null) {
4620            activity.mCalled = false;
4621        }
4622
4623        boolean shouldChangeConfig = false;
4624        if ((activity == null) || (activity.mCurrentConfig == null)) {
4625            shouldChangeConfig = true;
4626        } else {
4627            // If the new config is the same as the config this Activity
4628            // is already running with then don't bother calling
4629            // onConfigurationChanged
4630            int diff = activity.mCurrentConfig.diff(newConfig);
4631            if (diff != 0) {
4632                shouldChangeConfig = true;
4633            }
4634        }
4635
4636        if (shouldChangeConfig) {
4637            // Propagate the configuration change to the Activity and ResourcesManager.
4638
4639            // ContextThemeWrappers may override the configuration for that context.
4640            // We must check and apply any overrides defined.
4641            Configuration contextThemeWrapperOverrideConfig = null;
4642            if (cb instanceof ContextThemeWrapper) {
4643                final ContextThemeWrapper contextThemeWrapper = (ContextThemeWrapper) cb;
4644                contextThemeWrapperOverrideConfig = contextThemeWrapper.getOverrideConfiguration();
4645            }
4646
4647            // We only update an Activity's configuration if this is not a global
4648            // configuration change. This must also be done before the callback,
4649            // or else we violate the contract that the new resources are available
4650            // in {@link ComponentCallbacks2#onConfigurationChanged(Configuration)}.
4651            if (activityToken != null) {
4652                // Apply the ContextThemeWrapper override if necessary.
4653                // NOTE: Make sure the configurations are not modified, as they are treated
4654                // as immutable in many places.
4655                final Configuration finalOverrideConfig = createNewConfigAndUpdateIfNotNull(
4656                        amOverrideConfig, contextThemeWrapperOverrideConfig);
4657                mResourcesManager.updateResourcesForActivity(activityToken, finalOverrideConfig);
4658            }
4659
4660            if (reportToActivity) {
4661                // Apply the ContextThemeWrapper override if necessary.
4662                // NOTE: Make sure the configurations are not modified, as they are treated
4663                // as immutable in many places.
4664                final Configuration configToReport = createNewConfigAndUpdateIfNotNull(
4665                        newConfig, contextThemeWrapperOverrideConfig);
4666                cb.onConfigurationChanged(configToReport);
4667            }
4668
4669            if (activity != null) {
4670                if (reportToActivity && !activity.mCalled) {
4671                    throw new SuperNotCalledException(
4672                            "Activity " + activity.getLocalClassName() +
4673                            " did not call through to super.onConfigurationChanged()");
4674                }
4675                activity.mConfigChangeFlags = 0;
4676                activity.mCurrentConfig = new Configuration(newConfig);
4677            }
4678        }
4679    }
4680
4681    public final void applyConfigurationToResources(Configuration config) {
4682        synchronized (mResourcesManager) {
4683            mResourcesManager.applyConfigurationToResourcesLocked(config, null);
4684        }
4685    }
4686
4687    final Configuration applyCompatConfiguration(int displayDensity) {
4688        Configuration config = mConfiguration;
4689        if (mCompatConfiguration == null) {
4690            mCompatConfiguration = new Configuration();
4691        }
4692        mCompatConfiguration.setTo(mConfiguration);
4693        if (mResourcesManager.applyCompatConfigurationLocked(displayDensity,
4694                mCompatConfiguration)) {
4695            config = mCompatConfiguration;
4696        }
4697        return config;
4698    }
4699
4700    final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {
4701
4702        int configDiff = 0;
4703
4704        synchronized (mResourcesManager) {
4705            if (mPendingConfiguration != null) {
4706                if (!mPendingConfiguration.isOtherSeqNewer(config)) {
4707                    config = mPendingConfiguration;
4708                    mCurDefaultDisplayDpi = config.densityDpi;
4709                    updateDefaultDensity();
4710                }
4711                mPendingConfiguration = null;
4712            }
4713
4714            if (config == null) {
4715                return;
4716            }
4717
4718            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: "
4719                    + config);
4720
4721            mResourcesManager.applyConfigurationToResourcesLocked(config, compat);
4722            updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
4723                    mResourcesManager.getConfiguration().getLocales());
4724
4725            if (mConfiguration == null) {
4726                mConfiguration = new Configuration();
4727            }
4728            if (!mConfiguration.isOtherSeqNewer(config) && compat == null) {
4729                return;
4730            }
4731
4732            configDiff = mConfiguration.updateFrom(config);
4733            config = applyCompatConfiguration(mCurDefaultDisplayDpi);
4734
4735            final Theme systemTheme = getSystemContext().getTheme();
4736            if ((systemTheme.getChangingConfigurations() & configDiff) != 0) {
4737                systemTheme.rebase();
4738            }
4739        }
4740
4741        ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
4742
4743        freeTextLayoutCachesIfNeeded(configDiff);
4744
4745        if (callbacks != null) {
4746            final int N = callbacks.size();
4747            for (int i=0; i<N; i++) {
4748                ComponentCallbacks2 cb = callbacks.get(i);
4749                if (cb instanceof Activity) {
4750                    // If callback is an Activity - call corresponding method to consider override
4751                    // config and avoid onConfigurationChanged if it hasn't changed.
4752                    Activity a = (Activity) cb;
4753                    performConfigurationChangedForActivity(mActivities.get(a.getActivityToken()),
4754                            config, REPORT_TO_ACTIVITY);
4755                } else {
4756                    performConfigurationChanged(cb, null, config, null, REPORT_TO_ACTIVITY);
4757                }
4758            }
4759        }
4760    }
4761
4762    static void freeTextLayoutCachesIfNeeded(int configDiff) {
4763        if (configDiff != 0) {
4764            // Ask text layout engine to free its caches if there is a locale change
4765            boolean hasLocaleConfigChange = ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0);
4766            if (hasLocaleConfigChange) {
4767                Canvas.freeTextLayoutCaches();
4768                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Cleared TextLayout Caches");
4769            }
4770        }
4771    }
4772
4773    final void handleActivityConfigurationChanged(ActivityConfigChangeData data,
4774            boolean reportToActivity) {
4775        ActivityClientRecord r = mActivities.get(data.activityToken);
4776        if (r == null || r.activity == null) {
4777            return;
4778        }
4779
4780        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle activity config changed: "
4781                + r.activityInfo.name + ", with callback=" + reportToActivity);
4782
4783        r.overrideConfig = data.overrideConfig;
4784        performConfigurationChangedForActivity(r, mCompatConfiguration, reportToActivity);
4785        mSomeActivitiesChanged = true;
4786    }
4787
4788    final void handleProfilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) {
4789        if (start) {
4790            try {
4791                switch (profileType) {
4792                    default:
4793                        mProfiler.setProfiler(profilerInfo);
4794                        mProfiler.startProfiling();
4795                        break;
4796                }
4797            } catch (RuntimeException e) {
4798                Slog.w(TAG, "Profiling failed on path " + profilerInfo.profileFile
4799                        + " -- can the process access this path?");
4800            } finally {
4801                try {
4802                    profilerInfo.profileFd.close();
4803                } catch (IOException e) {
4804                    Slog.w(TAG, "Failure closing profile fd", e);
4805                }
4806            }
4807        } else {
4808            switch (profileType) {
4809                default:
4810                    mProfiler.stopProfiling();
4811                    break;
4812            }
4813        }
4814    }
4815
4816    /**
4817     * Public entrypoint to stop profiling. This is required to end profiling when the app crashes,
4818     * so that profiler data won't be lost.
4819     *
4820     * @hide
4821     */
4822    public void stopProfiling() {
4823        mProfiler.stopProfiling();
4824    }
4825
4826    static final void handleDumpHeap(boolean managed, DumpHeapData dhd) {
4827        if (managed) {
4828            try {
4829                Debug.dumpHprofData(dhd.path, dhd.fd.getFileDescriptor());
4830            } catch (IOException e) {
4831                Slog.w(TAG, "Managed heap dump failed on path " + dhd.path
4832                        + " -- can the process access this path?");
4833            } finally {
4834                try {
4835                    dhd.fd.close();
4836                } catch (IOException e) {
4837                    Slog.w(TAG, "Failure closing profile fd", e);
4838                }
4839            }
4840        } else {
4841            Debug.dumpNativeHeap(dhd.fd.getFileDescriptor());
4842        }
4843        try {
4844            ActivityManagerNative.getDefault().dumpHeapFinished(dhd.path);
4845        } catch (RemoteException e) {
4846            throw e.rethrowFromSystemServer();
4847        }
4848    }
4849
4850    final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
4851        boolean hasPkgInfo = false;
4852        switch (cmd) {
4853            case IApplicationThread.PACKAGE_REMOVED:
4854            case IApplicationThread.PACKAGE_REMOVED_DONT_KILL:
4855            {
4856                final boolean killApp = cmd == IApplicationThread.PACKAGE_REMOVED;
4857                if (packages == null) {
4858                    break;
4859                }
4860                synchronized (mResourcesManager) {
4861                    for (int i = packages.length - 1; i >= 0; i--) {
4862                        if (!hasPkgInfo) {
4863                            WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
4864                            if (ref != null && ref.get() != null) {
4865                                hasPkgInfo = true;
4866                            } else {
4867                                ref = mResourcePackages.get(packages[i]);
4868                                if (ref != null && ref.get() != null) {
4869                                    hasPkgInfo = true;
4870                                }
4871                            }
4872                        }
4873                        if (killApp) {
4874                            mPackages.remove(packages[i]);
4875                            mResourcePackages.remove(packages[i]);
4876                        }
4877                    }
4878                }
4879                break;
4880            }
4881            case IApplicationThread.PACKAGE_REPLACED:
4882            {
4883                if (packages == null) {
4884                    break;
4885                }
4886                synchronized (mResourcesManager) {
4887                    for (int i = packages.length - 1; i >= 0; i--) {
4888                        WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
4889                        LoadedApk pkgInfo = ref != null ? ref.get() : null;
4890                        if (pkgInfo != null) {
4891                            hasPkgInfo = true;
4892                        } else {
4893                            ref = mResourcePackages.get(packages[i]);
4894                            pkgInfo = ref != null ? ref.get() : null;
4895                            if (pkgInfo != null) {
4896                                hasPkgInfo = true;
4897                            }
4898                        }
4899                        // If the package is being replaced, yet it still has a valid