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