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