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