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