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