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