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