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