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