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