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