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