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