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