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