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