Some ActivityThread/ActivityManager cleanup.
- Move PackageInfo out of ActivityThread, renaming to LoadedApk.
- Rename some of the other PacakgeInfo inner classes to better
represent what they are.
- Rename HistoryRecord to ActivityRecord.
- Introduce AppGlobals, to eventually let ActivityThread become
package scoped.
Change-Id: Ib714c54ceb3cdbb525dce3db9505f31042e88cf0
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 0ce790e..6599096 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -25,7 +25,6 @@
import android.content.IContentProvider;
import android.content.Intent;
import android.content.IIntentReceiver;
-import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
@@ -74,7 +73,6 @@
import com.android.internal.os.BinderInternal;
import com.android.internal.os.RuntimeInit;
import com.android.internal.os.SamplingProfilerIntegration;
-import com.android.internal.util.ArrayUtils;
import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
@@ -82,12 +80,9 @@
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
-import java.net.URL;
import java.util.ArrayList;
-import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -98,18 +93,6 @@
import dalvik.system.SamplingProfiler;
-final class IntentReceiverLeaked extends AndroidRuntimeException {
- public IntentReceiverLeaked(String msg) {
- super(msg);
- }
-}
-
-final class ServiceConnectionLeaked extends AndroidRuntimeException {
- public ServiceConnectionLeaked(String msg) {
- super(msg);
- }
-}
-
final class SuperNotCalledException extends AndroidRuntimeException {
public SuperNotCalledException(String msg) {
super(msg);
@@ -125,10 +108,10 @@
* {@hide}
*/
public final class ActivityThread {
- private static final String TAG = "ActivityThread";
+ static final String TAG = "ActivityThread";
private static final boolean DEBUG = false;
- private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
- private static final boolean DEBUG_BROADCAST = false;
+ static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
+ static final boolean DEBUG_BROADCAST = false;
private static final boolean DEBUG_RESULTS = false;
private static final boolean DEBUG_BACKUP = false;
private static final boolean DEBUG_CONFIGURATION = false;
@@ -138,1162 +121,65 @@
private static final int LOG_ON_PAUSE_CALLED = 30021;
private static final int LOG_ON_RESUME_CALLED = 30022;
+ static ContextImpl mSystemContext = null;
- public static final ActivityThread currentActivityThread() {
- return (ActivityThread)sThreadLocal.get();
- }
+ static IPackageManager sPackageManager;
- public static final String currentPackageName()
- {
- ActivityThread am = currentActivityThread();
- return (am != null && am.mBoundApplication != null)
- ? am.mBoundApplication.processName : null;
- }
+ final ApplicationThread mAppThread = new ApplicationThread();
+ final Looper mLooper = Looper.myLooper();
+ final H mH = new H();
+ final HashMap<IBinder, ActivityClientRecord> mActivities
+ = new HashMap<IBinder, ActivityClientRecord>();
+ // List of new activities (via ActivityRecord.nextIdle) that should
+ // be reported when next we idle.
+ ActivityClientRecord mNewActivities = null;
+ // Number of activities that are currently visible on-screen.
+ int mNumVisibleActivities = 0;
+ final HashMap<IBinder, Service> mServices
+ = new HashMap<IBinder, Service>();
+ AppBindData mBoundApplication;
+ Configuration mConfiguration;
+ Configuration mResConfiguration;
+ Application mInitialApplication;
+ final ArrayList<Application> mAllApplications
+ = new ArrayList<Application>();
+ // set of instantiated backup agents, keyed by package name
+ final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>();
+ static final ThreadLocal sThreadLocal = new ThreadLocal();
+ Instrumentation mInstrumentation;
+ String mInstrumentationAppDir = null;
+ String mInstrumentationAppPackage = null;
+ String mInstrumentedAppDir = null;
+ boolean mSystemThread = false;
+ boolean mJitEnabled = false;
- public static IPackageManager getPackageManager() {
- if (sPackageManager != null) {
- //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
- return sPackageManager;
- }
- IBinder b = ServiceManager.getService("package");
- //Slog.v("PackageManager", "default service binder = " + b);
- sPackageManager = IPackageManager.Stub.asInterface(b);
- //Slog.v("PackageManager", "default service = " + sPackageManager);
- return sPackageManager;
- }
+ // These can be accessed by multiple threads; mPackages is the lock.
+ // XXX For now we keep around information about all packages we have
+ // seen, not removing entries from this map.
+ final HashMap<String, WeakReference<LoadedApk>> mPackages
+ = new HashMap<String, WeakReference<LoadedApk>>();
+ final HashMap<String, WeakReference<LoadedApk>> mResourcePackages
+ = new HashMap<String, WeakReference<LoadedApk>>();
+ Display mDisplay = null;
+ DisplayMetrics mDisplayMetrics = null;
+ final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
+ = new HashMap<ResourcesKey, WeakReference<Resources> >();
+ final ArrayList<ActivityClientRecord> mRelaunchingActivities
+ = new ArrayList<ActivityClientRecord>();
+ Configuration mPendingConfiguration = null;
- DisplayMetrics getDisplayMetricsLocked(boolean forceUpdate) {
- if (mDisplayMetrics != null && !forceUpdate) {
- return mDisplayMetrics;
- }
- if (mDisplay == null) {
- WindowManager wm = WindowManagerImpl.getDefault();
- mDisplay = wm.getDefaultDisplay();
- }
- DisplayMetrics metrics = mDisplayMetrics = new DisplayMetrics();
- mDisplay.getMetrics(metrics);
- //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
- // + metrics.heightPixels + " den=" + metrics.density
- // + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
- return metrics;
- }
+ // The lock of mProviderMap protects the following variables.
+ final HashMap<String, ProviderClientRecord> mProviderMap
+ = new HashMap<String, ProviderClientRecord>();
+ final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap
+ = new HashMap<IBinder, ProviderRefCount>();
+ final HashMap<IBinder, ProviderClientRecord> mLocalProviders
+ = new HashMap<IBinder, ProviderClientRecord>();
- /**
- * Creates the top level Resources for applications with the given compatibility info.
- *
- * @param resDir the resource directory.
- * @param compInfo the compability info. It will use the default compatibility info when it's
- * null.
- */
- Resources getTopLevelResources(String resDir, CompatibilityInfo compInfo) {
- ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale);
- Resources r;
- synchronized (mPackages) {
- // Resources is app scale dependent.
- if (false) {
- Slog.w(TAG, "getTopLevelResources: " + resDir + " / "
- + compInfo.applicationScale);
- }
- WeakReference<Resources> wr = mActiveResources.get(key);
- r = wr != null ? wr.get() : null;
- //if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
- if (r != null && r.getAssets().isUpToDate()) {
- if (false) {
- Slog.w(TAG, "Returning cached resources " + r + " " + resDir
- + ": appScale=" + r.getCompatibilityInfo().applicationScale);
- }
- return r;
- }
- }
+ final GcIdler mGcIdler = new GcIdler();
+ boolean mGcIdlerScheduled = false;
- //if (r != null) {
- // Slog.w(TAG, "Throwing away out-of-date resources!!!! "
- // + r + " " + resDir);
- //}
-
- AssetManager assets = new AssetManager();
- if (assets.addAssetPath(resDir) == 0) {
- return null;
- }
-
- //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
- DisplayMetrics metrics = getDisplayMetricsLocked(false);
- r = new Resources(assets, metrics, getConfiguration(), compInfo);
- if (false) {
- Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
- + r.getConfiguration() + " appScale="
- + r.getCompatibilityInfo().applicationScale);
- }
-
- synchronized (mPackages) {
- WeakReference<Resources> wr = mActiveResources.get(key);
- Resources existing = wr != null ? wr.get() : null;
- if (existing != null && existing.getAssets().isUpToDate()) {
- // Someone else already created the resources while we were
- // unlocked; go ahead and use theirs.
- r.getAssets().close();
- return existing;
- }
-
- // XXX need to remove entries when weak references go away
- mActiveResources.put(key, new WeakReference<Resources>(r));
- return r;
- }
- }
-
- /**
- * Creates the top level resources for the given package.
- */
- Resources getTopLevelResources(String resDir, PackageInfo pkgInfo) {
- return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo);
- }
-
- final Handler getHandler() {
- return mH;
- }
-
- public final static class PackageInfo {
-
- private final ActivityThread mActivityThread;
- private final ApplicationInfo mApplicationInfo;
- private final String mPackageName;
- private final String mAppDir;
- private final String mResDir;
- private final String[] mSharedLibraries;
- private final String mDataDir;
- private final File mDataDirFile;
- private final ClassLoader mBaseClassLoader;
- private final boolean mSecurityViolation;
- private final boolean mIncludeCode;
- private Resources mResources;
- private ClassLoader mClassLoader;
- private Application mApplication;
- private CompatibilityInfo mCompatibilityInfo;
-
- private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
- = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
- private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mUnregisteredReceivers
- = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
- private final HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>> mServices
- = new HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>>();
- private final HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>> mUnboundServices
- = new HashMap<Context, HashMap<ServiceConnection, ServiceDispatcher>>();
-
- int mClientCount = 0;
-
- Application getApplication() {
- return mApplication;
- }
-
- public PackageInfo(ActivityThread activityThread, ApplicationInfo aInfo,
- ActivityThread mainThread, ClassLoader baseLoader,
- boolean securityViolation, boolean includeCode) {
- mActivityThread = activityThread;
- mApplicationInfo = aInfo;
- mPackageName = aInfo.packageName;
- mAppDir = aInfo.sourceDir;
- mResDir = aInfo.uid == Process.myUid() ? aInfo.sourceDir
- : aInfo.publicSourceDir;
- mSharedLibraries = aInfo.sharedLibraryFiles;
- mDataDir = aInfo.dataDir;
- mDataDirFile = mDataDir != null ? new File(mDataDir) : null;
- mBaseClassLoader = baseLoader;
- mSecurityViolation = securityViolation;
- mIncludeCode = includeCode;
- mCompatibilityInfo = new CompatibilityInfo(aInfo);
-
- if (mAppDir == null) {
- if (mSystemContext == null) {
- mSystemContext =
- ContextImpl.createSystemContext(mainThread);
- mSystemContext.getResources().updateConfiguration(
- mainThread.getConfiguration(),
- mainThread.getDisplayMetricsLocked(false));
- //Slog.i(TAG, "Created system resources "
- // + mSystemContext.getResources() + ": "
- // + mSystemContext.getResources().getConfiguration());
- }
- mClassLoader = mSystemContext.getClassLoader();
- mResources = mSystemContext.getResources();
- }
- }
-
- public PackageInfo(ActivityThread activityThread, String name,
- Context systemContext, ApplicationInfo info) {
- mActivityThread = activityThread;
- mApplicationInfo = info != null ? info : new ApplicationInfo();
- mApplicationInfo.packageName = name;
- mPackageName = name;
- mAppDir = null;
- mResDir = null;
- mSharedLibraries = null;
- mDataDir = null;
- mDataDirFile = null;
- mBaseClassLoader = null;
- mSecurityViolation = false;
- mIncludeCode = true;
- mClassLoader = systemContext.getClassLoader();
- mResources = systemContext.getResources();
- mCompatibilityInfo = new CompatibilityInfo(mApplicationInfo);
- }
-
- public String getPackageName() {
- return mPackageName;
- }
-
- public ApplicationInfo getApplicationInfo() {
- return mApplicationInfo;
- }
-
- public boolean isSecurityViolation() {
- return mSecurityViolation;
- }
-
- /**
- * Gets the array of shared libraries that are listed as
- * used by the given package.
- *
- * @param packageName the name of the package (note: not its
- * file name)
- * @return null-ok; the array of shared libraries, each one
- * a fully-qualified path
- */
- private static String[] getLibrariesFor(String packageName) {
- ApplicationInfo ai = null;
- try {
- ai = getPackageManager().getApplicationInfo(packageName,
- PackageManager.GET_SHARED_LIBRARY_FILES);
- } catch (RemoteException e) {
- throw new AssertionError(e);
- }
-
- if (ai == null) {
- return null;
- }
-
- return ai.sharedLibraryFiles;
- }
-
- /**
- * Combines two arrays (of library names) such that they are
- * concatenated in order but are devoid of duplicates. The
- * result is a single string with the names of the libraries
- * separated by colons, or <code>null</code> if both lists
- * were <code>null</code> or empty.
- *
- * @param list1 null-ok; the first list
- * @param list2 null-ok; the second list
- * @return null-ok; the combination
- */
- private static String combineLibs(String[] list1, String[] list2) {
- StringBuilder result = new StringBuilder(300);
- boolean first = true;
-
- if (list1 != null) {
- for (String s : list1) {
- if (first) {
- first = false;
- } else {
- result.append(':');
- }
- result.append(s);
- }
- }
-
- // Only need to check for duplicates if list1 was non-empty.
- boolean dupCheck = !first;
-
- if (list2 != null) {
- for (String s : list2) {
- if (dupCheck && ArrayUtils.contains(list1, s)) {
- continue;
- }
-
- if (first) {
- first = false;
- } else {
- result.append(':');
- }
- result.append(s);
- }
- }
-
- return result.toString();
- }
-
- public ClassLoader getClassLoader() {
- synchronized (this) {
- if (mClassLoader != null) {
- return mClassLoader;
- }
-
- if (mIncludeCode && !mPackageName.equals("android")) {
- String zip = mAppDir;
-
- /*
- * The following is a bit of a hack to inject
- * instrumentation into the system: If the app
- * being started matches one of the instrumentation names,
- * then we combine both the "instrumentation" and
- * "instrumented" app into the path, along with the
- * concatenation of both apps' shared library lists.
- */
-
- String instrumentationAppDir =
- mActivityThread.mInstrumentationAppDir;
- String instrumentationAppPackage =
- mActivityThread.mInstrumentationAppPackage;
- String instrumentedAppDir =
- mActivityThread.mInstrumentedAppDir;
- String[] instrumentationLibs = null;
-
- if (mAppDir.equals(instrumentationAppDir)
- || mAppDir.equals(instrumentedAppDir)) {
- zip = instrumentationAppDir + ":" + instrumentedAppDir;
- if (! instrumentedAppDir.equals(instrumentationAppDir)) {
- instrumentationLibs =
- getLibrariesFor(instrumentationAppPackage);
- }
- }
-
- if ((mSharedLibraries != null) ||
- (instrumentationLibs != null)) {
- zip =
- combineLibs(mSharedLibraries, instrumentationLibs)
- + ':' + zip;
- }
-
- /*
- * With all the combination done (if necessary, actually
- * create the class loader.
- */
-
- if (localLOGV) Slog.v(TAG, "Class path: " + zip);
-
- mClassLoader =
- ApplicationLoaders.getDefault().getClassLoader(
- zip, mDataDir, mBaseClassLoader);
- initializeJavaContextClassLoader();
- } else {
- if (mBaseClassLoader == null) {
- mClassLoader = ClassLoader.getSystemClassLoader();
- } else {
- mClassLoader = mBaseClassLoader;
- }
- }
- return mClassLoader;
- }
- }
-
- /**
- * Setup value for Thread.getContextClassLoader(). If the
- * package will not run in in a VM with other packages, we set
- * the Java context ClassLoader to the
- * PackageInfo.getClassLoader value. However, if this VM can
- * contain multiple packages, we intead set the Java context
- * ClassLoader to a proxy that will warn about the use of Java
- * context ClassLoaders and then fall through to use the
- * system ClassLoader.
- *
- * <p> Note that this is similar to but not the same as the
- * android.content.Context.getClassLoader(). While both
- * context class loaders are typically set to the
- * PathClassLoader used to load the package archive in the
- * single application per VM case, a single Android process
- * may contain several Contexts executing on one thread with
- * their own logical ClassLoaders while the Java context
- * ClassLoader is a thread local. This is why in the case when
- * we have multiple packages per VM we do not set the Java
- * context ClassLoader to an arbitrary but instead warn the
- * user to set their own if we detect that they are using a
- * Java library that expects it to be set.
- */
- private void initializeJavaContextClassLoader() {
- IPackageManager pm = getPackageManager();
- android.content.pm.PackageInfo pi;
- try {
- pi = pm.getPackageInfo(mPackageName, 0);
- } catch (RemoteException e) {
- throw new AssertionError(e);
- }
- /*
- * Two possible indications that this package could be
- * sharing its virtual machine with other packages:
- *
- * 1.) the sharedUserId attribute is set in the manifest,
- * indicating a request to share a VM with other
- * packages with the same sharedUserId.
- *
- * 2.) the application element of the manifest has an
- * attribute specifying a non-default process name,
- * indicating the desire to run in another packages VM.
- */
- boolean sharedUserIdSet = (pi.sharedUserId != null);
- boolean processNameNotDefault =
- (pi.applicationInfo != null &&
- !mPackageName.equals(pi.applicationInfo.processName));
- boolean sharable = (sharedUserIdSet || processNameNotDefault);
- ClassLoader contextClassLoader =
- (sharable)
- ? new WarningContextClassLoader()
- : mClassLoader;
- Thread.currentThread().setContextClassLoader(contextClassLoader);
- }
-
- private static class WarningContextClassLoader extends ClassLoader {
-
- private static boolean warned = false;
-
- private void warn(String methodName) {
- if (warned) {
- return;
- }
- warned = true;
- Thread.currentThread().setContextClassLoader(getParent());
- Slog.w(TAG, "ClassLoader." + methodName + ": " +
- "The class loader returned by " +
- "Thread.getContextClassLoader() may fail for processes " +
- "that host multiple applications. You should explicitly " +
- "specify a context class loader. For example: " +
- "Thread.setContextClassLoader(getClass().getClassLoader());");
- }
-
- @Override public URL getResource(String resName) {
- warn("getResource");
- return getParent().getResource(resName);
- }
-
- @Override public Enumeration<URL> getResources(String resName) throws IOException {
- warn("getResources");
- return getParent().getResources(resName);
- }
-
- @Override public InputStream getResourceAsStream(String resName) {
- warn("getResourceAsStream");
- return getParent().getResourceAsStream(resName);
- }
-
- @Override public Class<?> loadClass(String className) throws ClassNotFoundException {
- warn("loadClass");
- return getParent().loadClass(className);
- }
-
- @Override public void setClassAssertionStatus(String cname, boolean enable) {
- warn("setClassAssertionStatus");
- getParent().setClassAssertionStatus(cname, enable);
- }
-
- @Override public void setPackageAssertionStatus(String pname, boolean enable) {
- warn("setPackageAssertionStatus");
- getParent().setPackageAssertionStatus(pname, enable);
- }
-
- @Override public void setDefaultAssertionStatus(boolean enable) {
- warn("setDefaultAssertionStatus");
- getParent().setDefaultAssertionStatus(enable);
- }
-
- @Override public void clearAssertionStatus() {
- warn("clearAssertionStatus");
- getParent().clearAssertionStatus();
- }
- }
-
- public String getAppDir() {
- return mAppDir;
- }
-
- public String getResDir() {
- return mResDir;
- }
-
- public String getDataDir() {
- return mDataDir;
- }
-
- public File getDataDirFile() {
- return mDataDirFile;
- }
-
- public AssetManager getAssets(ActivityThread mainThread) {
- return getResources(mainThread).getAssets();
- }
-
- public Resources getResources(ActivityThread mainThread) {
- if (mResources == null) {
- mResources = mainThread.getTopLevelResources(mResDir, this);
- }
- return mResources;
- }
-
- public Application makeApplication(boolean forceDefaultAppClass,
- Instrumentation instrumentation) {
- if (mApplication != null) {
- return mApplication;
- }
-
- Application app = null;
-
- String appClass = mApplicationInfo.className;
- if (forceDefaultAppClass || (appClass == null)) {
- appClass = "android.app.Application";
- }
-
- try {
- java.lang.ClassLoader cl = getClassLoader();
- ContextImpl appContext = new ContextImpl();
- appContext.init(this, null, mActivityThread);
- app = mActivityThread.mInstrumentation.newApplication(
- cl, appClass, appContext);
- appContext.setOuterContext(app);
- } catch (Exception e) {
- if (!mActivityThread.mInstrumentation.onException(app, e)) {
- throw new RuntimeException(
- "Unable to instantiate application " + appClass
- + ": " + e.toString(), e);
- }
- }
- mActivityThread.mAllApplications.add(app);
- mApplication = app;
-
- if (instrumentation != null) {
- try {
- instrumentation.callApplicationOnCreate(app);
- } catch (Exception e) {
- if (!instrumentation.onException(app, e)) {
- throw new RuntimeException(
- "Unable to create application " + app.getClass().getName()
- + ": " + e.toString(), e);
- }
- }
- }
-
- return app;
- }
-
- public void removeContextRegistrations(Context context,
- String who, String what) {
- HashMap<BroadcastReceiver, ReceiverDispatcher> rmap =
- mReceivers.remove(context);
- if (rmap != null) {
- Iterator<ReceiverDispatcher> it = rmap.values().iterator();
- while (it.hasNext()) {
- ReceiverDispatcher rd = it.next();
- IntentReceiverLeaked leak = new IntentReceiverLeaked(
- what + " " + who + " has leaked IntentReceiver "
- + rd.getIntentReceiver() + " that was " +
- "originally registered here. Are you missing a " +
- "call to unregisterReceiver()?");
- leak.setStackTrace(rd.getLocation().getStackTrace());
- Slog.e(TAG, leak.getMessage(), leak);
- try {
- ActivityManagerNative.getDefault().unregisterReceiver(
- rd.getIIntentReceiver());
- } catch (RemoteException e) {
- // system crashed, nothing we can do
- }
- }
- }
- mUnregisteredReceivers.remove(context);
- //Slog.i(TAG, "Receiver registrations: " + mReceivers);
- HashMap<ServiceConnection, ServiceDispatcher> smap =
- mServices.remove(context);
- if (smap != null) {
- Iterator<ServiceDispatcher> it = smap.values().iterator();
- while (it.hasNext()) {
- ServiceDispatcher sd = it.next();
- ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
- what + " " + who + " has leaked ServiceConnection "
- + sd.getServiceConnection() + " that was originally bound here");
- leak.setStackTrace(sd.getLocation().getStackTrace());
- Slog.e(TAG, leak.getMessage(), leak);
- try {
- ActivityManagerNative.getDefault().unbindService(
- sd.getIServiceConnection());
- } catch (RemoteException e) {
- // system crashed, nothing we can do
- }
- sd.doForget();
- }
- }
- mUnboundServices.remove(context);
- //Slog.i(TAG, "Service registrations: " + mServices);
- }
-
- public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
- Context context, Handler handler,
- Instrumentation instrumentation, boolean registered) {
- synchronized (mReceivers) {
- ReceiverDispatcher rd = null;
- HashMap<BroadcastReceiver, ReceiverDispatcher> map = null;
- if (registered) {
- map = mReceivers.get(context);
- if (map != null) {
- rd = map.get(r);
- }
- }
- if (rd == null) {
- rd = new ReceiverDispatcher(r, context, handler,
- instrumentation, registered);
- if (registered) {
- if (map == null) {
- map = new HashMap<BroadcastReceiver, ReceiverDispatcher>();
- mReceivers.put(context, map);
- }
- map.put(r, rd);
- }
- } else {
- rd.validate(context, handler);
- }
- return rd.getIIntentReceiver();
- }
- }
-
- public IIntentReceiver forgetReceiverDispatcher(Context context,
- BroadcastReceiver r) {
- synchronized (mReceivers) {
- HashMap<BroadcastReceiver, ReceiverDispatcher> map = mReceivers.get(context);
- ReceiverDispatcher rd = null;
- if (map != null) {
- rd = map.get(r);
- if (rd != null) {
- map.remove(r);
- if (map.size() == 0) {
- mReceivers.remove(context);
- }
- if (r.getDebugUnregister()) {
- HashMap<BroadcastReceiver, ReceiverDispatcher> holder
- = mUnregisteredReceivers.get(context);
- if (holder == null) {
- holder = new HashMap<BroadcastReceiver, ReceiverDispatcher>();
- mUnregisteredReceivers.put(context, holder);
- }
- RuntimeException ex = new IllegalArgumentException(
- "Originally unregistered here:");
- ex.fillInStackTrace();
- rd.setUnregisterLocation(ex);
- holder.put(r, rd);
- }
- return rd.getIIntentReceiver();
- }
- }
- HashMap<BroadcastReceiver, ReceiverDispatcher> holder
- = mUnregisteredReceivers.get(context);
- if (holder != null) {
- rd = holder.get(r);
- if (rd != null) {
- RuntimeException ex = rd.getUnregisterLocation();
- throw new IllegalArgumentException(
- "Unregistering Receiver " + r
- + " that was already unregistered", ex);
- }
- }
- if (context == null) {
- throw new IllegalStateException("Unbinding Receiver " + r
- + " from Context that is no longer in use: " + context);
- } else {
- throw new IllegalArgumentException("Receiver not registered: " + r);
- }
-
- }
- }
-
- static final class ReceiverDispatcher {
-
- final static class InnerReceiver extends IIntentReceiver.Stub {
- final WeakReference<ReceiverDispatcher> mDispatcher;
- final ReceiverDispatcher mStrongRef;
-
- InnerReceiver(ReceiverDispatcher rd, boolean strong) {
- mDispatcher = new WeakReference<ReceiverDispatcher>(rd);
- mStrongRef = strong ? rd : null;
- }
- public void performReceive(Intent intent, int resultCode,
- String data, Bundle extras, boolean ordered, boolean sticky) {
- ReceiverDispatcher rd = mDispatcher.get();
- if (DEBUG_BROADCAST) {
- int seq = intent.getIntExtra("seq", -1);
- Slog.i(TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
- + " to " + (rd != null ? rd.mReceiver : null));
- }
- if (rd != null) {
- rd.performReceive(intent, resultCode, data, extras,
- ordered, sticky);
- } else {
- // The activity manager dispatched a broadcast to a registered
- // receiver in this process, but before it could be delivered the
- // receiver was unregistered. Acknowledge the broadcast on its
- // behalf so that the system's broadcast sequence can continue.
- if (DEBUG_BROADCAST) Slog.i(TAG,
- "Finishing broadcast to unregistered receiver");
- IActivityManager mgr = ActivityManagerNative.getDefault();
- try {
- mgr.finishReceiver(this, resultCode, data, extras, false);
- } catch (RemoteException e) {
- Slog.w(TAG, "Couldn't finish broadcast to unregistered receiver");
- }
- }
- }
- }
-
- final IIntentReceiver.Stub mIIntentReceiver;
- final BroadcastReceiver mReceiver;
- final Context mContext;
- final Handler mActivityThread;
- final Instrumentation mInstrumentation;
- final boolean mRegistered;
- final IntentReceiverLeaked mLocation;
- RuntimeException mUnregisterLocation;
-
- final class Args implements Runnable {
- private Intent mCurIntent;
- private int mCurCode;
- private String mCurData;
- private Bundle mCurMap;
- private boolean mCurOrdered;
- private boolean mCurSticky;
-
- public void run() {
- BroadcastReceiver receiver = mReceiver;
- if (DEBUG_BROADCAST) {
- int seq = mCurIntent.getIntExtra("seq", -1);
- Slog.i(TAG, "Dispatching broadcast " + mCurIntent.getAction()
- + " seq=" + seq + " to " + mReceiver);
- Slog.i(TAG, " mRegistered=" + mRegistered
- + " mCurOrdered=" + mCurOrdered);
- }
-
- IActivityManager mgr = ActivityManagerNative.getDefault();
- Intent intent = mCurIntent;
- mCurIntent = null;
-
- if (receiver == null) {
- if (mRegistered && mCurOrdered) {
- try {
- if (DEBUG_BROADCAST) Slog.i(TAG,
- "Finishing null broadcast to " + mReceiver);
- mgr.finishReceiver(mIIntentReceiver,
- mCurCode, mCurData, mCurMap, false);
- } catch (RemoteException ex) {
- }
- }
- return;
- }
-
- try {
- ClassLoader cl = mReceiver.getClass().getClassLoader();
- intent.setExtrasClassLoader(cl);
- if (mCurMap != null) {
- mCurMap.setClassLoader(cl);
- }
- receiver.setOrderedHint(true);
- receiver.setResult(mCurCode, mCurData, mCurMap);
- receiver.clearAbortBroadcast();
- receiver.setOrderedHint(mCurOrdered);
- receiver.setInitialStickyHint(mCurSticky);
- receiver.onReceive(mContext, intent);
- } catch (Exception e) {
- if (mRegistered && mCurOrdered) {
- try {
- if (DEBUG_BROADCAST) Slog.i(TAG,
- "Finishing failed broadcast to " + mReceiver);
- mgr.finishReceiver(mIIntentReceiver,
- mCurCode, mCurData, mCurMap, false);
- } catch (RemoteException ex) {
- }
- }
- if (mInstrumentation == null ||
- !mInstrumentation.onException(mReceiver, e)) {
- throw new RuntimeException(
- "Error receiving broadcast " + intent
- + " in " + mReceiver, e);
- }
- }
- if (mRegistered && mCurOrdered) {
- try {
- if (DEBUG_BROADCAST) Slog.i(TAG,
- "Finishing broadcast to " + mReceiver);
- mgr.finishReceiver(mIIntentReceiver,
- receiver.getResultCode(),
- receiver.getResultData(),
- receiver.getResultExtras(false),
- receiver.getAbortBroadcast());
- } catch (RemoteException ex) {
- }
- }
- }
- }
-
- ReceiverDispatcher(BroadcastReceiver receiver, Context context,
- Handler activityThread, Instrumentation instrumentation,
- boolean registered) {
- if (activityThread == null) {
- throw new NullPointerException("Handler must not be null");
- }
-
- mIIntentReceiver = new InnerReceiver(this, !registered);
- mReceiver = receiver;
- mContext = context;
- mActivityThread = activityThread;
- mInstrumentation = instrumentation;
- mRegistered = registered;
- mLocation = new IntentReceiverLeaked(null);
- mLocation.fillInStackTrace();
- }
-
- void validate(Context context, Handler activityThread) {
- if (mContext != context) {
- throw new IllegalStateException(
- "Receiver " + mReceiver +
- " registered with differing Context (was " +
- mContext + " now " + context + ")");
- }
- if (mActivityThread != activityThread) {
- throw new IllegalStateException(
- "Receiver " + mReceiver +
- " registered with differing handler (was " +
- mActivityThread + " now " + activityThread + ")");
- }
- }
-
- IntentReceiverLeaked getLocation() {
- return mLocation;
- }
-
- BroadcastReceiver getIntentReceiver() {
- return mReceiver;
- }
-
- IIntentReceiver getIIntentReceiver() {
- return mIIntentReceiver;
- }
-
- void setUnregisterLocation(RuntimeException ex) {
- mUnregisterLocation = ex;
- }
-
- RuntimeException getUnregisterLocation() {
- return mUnregisterLocation;
- }
-
- public void performReceive(Intent intent, int resultCode,
- String data, Bundle extras, boolean ordered, boolean sticky) {
- if (DEBUG_BROADCAST) {
- int seq = intent.getIntExtra("seq", -1);
- Slog.i(TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
- + " to " + mReceiver);
- }
- Args args = new Args();
- args.mCurIntent = intent;
- args.mCurCode = resultCode;
- args.mCurData = data;
- args.mCurMap = extras;
- args.mCurOrdered = ordered;
- args.mCurSticky = sticky;
- if (!mActivityThread.post(args)) {
- if (mRegistered && ordered) {
- IActivityManager mgr = ActivityManagerNative.getDefault();
- try {
- if (DEBUG_BROADCAST) Slog.i(TAG,
- "Finishing sync broadcast to " + mReceiver);
- mgr.finishReceiver(mIIntentReceiver, args.mCurCode,
- args.mCurData, args.mCurMap, false);
- } catch (RemoteException ex) {
- }
- }
- }
- }
-
- }
-
- public final IServiceConnection getServiceDispatcher(ServiceConnection c,
- Context context, Handler handler, int flags) {
- synchronized (mServices) {
- ServiceDispatcher sd = null;
- HashMap<ServiceConnection, ServiceDispatcher> map = mServices.get(context);
- if (map != null) {
- sd = map.get(c);
- }
- if (sd == null) {
- sd = new ServiceDispatcher(c, context, handler, flags);
- if (map == null) {
- map = new HashMap<ServiceConnection, ServiceDispatcher>();
- mServices.put(context, map);
- }
- map.put(c, sd);
- } else {
- sd.validate(context, handler);
- }
- return sd.getIServiceConnection();
- }
- }
-
- public final IServiceConnection forgetServiceDispatcher(Context context,
- ServiceConnection c) {
- synchronized (mServices) {
- HashMap<ServiceConnection, ServiceDispatcher> map
- = mServices.get(context);
- ServiceDispatcher sd = null;
- if (map != null) {
- sd = map.get(c);
- if (sd != null) {
- map.remove(c);
- sd.doForget();
- if (map.size() == 0) {
- mServices.remove(context);
- }
- if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
- HashMap<ServiceConnection, ServiceDispatcher> holder
- = mUnboundServices.get(context);
- if (holder == null) {
- holder = new HashMap<ServiceConnection, ServiceDispatcher>();
- mUnboundServices.put(context, holder);
- }
- RuntimeException ex = new IllegalArgumentException(
- "Originally unbound here:");
- ex.fillInStackTrace();
- sd.setUnbindLocation(ex);
- holder.put(c, sd);
- }
- return sd.getIServiceConnection();
- }
- }
- HashMap<ServiceConnection, ServiceDispatcher> holder
- = mUnboundServices.get(context);
- if (holder != null) {
- sd = holder.get(c);
- if (sd != null) {
- RuntimeException ex = sd.getUnbindLocation();
- throw new IllegalArgumentException(
- "Unbinding Service " + c
- + " that was already unbound", ex);
- }
- }
- if (context == null) {
- throw new IllegalStateException("Unbinding Service " + c
- + " from Context that is no longer in use: " + context);
- } else {
- throw new IllegalArgumentException("Service not registered: " + c);
- }
- }
- }
-
- static final class ServiceDispatcher {
- private final InnerConnection mIServiceConnection;
- private final ServiceConnection mConnection;
- private final Context mContext;
- private final Handler mActivityThread;
- private final ServiceConnectionLeaked mLocation;
- private final int mFlags;
-
- private RuntimeException mUnbindLocation;
-
- private boolean mDied;
-
- private static class ConnectionInfo {
- IBinder binder;
- IBinder.DeathRecipient deathMonitor;
- }
-
- private static class InnerConnection extends IServiceConnection.Stub {
- final WeakReference<ServiceDispatcher> mDispatcher;
-
- InnerConnection(ServiceDispatcher sd) {
- mDispatcher = new WeakReference<ServiceDispatcher>(sd);
- }
-
- public void connected(ComponentName name, IBinder service) throws RemoteException {
- ServiceDispatcher sd = mDispatcher.get();
- if (sd != null) {
- sd.connected(name, service);
- }
- }
- }
-
- private final HashMap<ComponentName, ConnectionInfo> mActiveConnections
- = new HashMap<ComponentName, ConnectionInfo>();
-
- ServiceDispatcher(ServiceConnection conn,
- Context context, Handler activityThread, int flags) {
- mIServiceConnection = new InnerConnection(this);
- mConnection = conn;
- mContext = context;
- mActivityThread = activityThread;
- mLocation = new ServiceConnectionLeaked(null);
- mLocation.fillInStackTrace();
- mFlags = flags;
- }
-
- void validate(Context context, Handler activityThread) {
- if (mContext != context) {
- throw new RuntimeException(
- "ServiceConnection " + mConnection +
- " registered with differing Context (was " +
- mContext + " now " + context + ")");
- }
- if (mActivityThread != activityThread) {
- throw new RuntimeException(
- "ServiceConnection " + mConnection +
- " registered with differing handler (was " +
- mActivityThread + " now " + activityThread + ")");
- }
- }
-
- void doForget() {
- synchronized(this) {
- Iterator<ConnectionInfo> it = mActiveConnections.values().iterator();
- while (it.hasNext()) {
- ConnectionInfo ci = it.next();
- ci.binder.unlinkToDeath(ci.deathMonitor, 0);
- }
- mActiveConnections.clear();
- }
- }
-
- ServiceConnectionLeaked getLocation() {
- return mLocation;
- }
-
- ServiceConnection getServiceConnection() {
- return mConnection;
- }
-
- IServiceConnection getIServiceConnection() {
- return mIServiceConnection;
- }
-
- int getFlags() {
- return mFlags;
- }
-
- void setUnbindLocation(RuntimeException ex) {
- mUnbindLocation = ex;
- }
-
- RuntimeException getUnbindLocation() {
- return mUnbindLocation;
- }
-
- public void connected(ComponentName name, IBinder service) {
- if (mActivityThread != null) {
- mActivityThread.post(new RunConnection(name, service, 0));
- } else {
- doConnected(name, service);
- }
- }
-
- public void death(ComponentName name, IBinder service) {
- ConnectionInfo old;
-
- synchronized (this) {
- mDied = true;
- old = mActiveConnections.remove(name);
- if (old == null || old.binder != service) {
- // Death for someone different than who we last
- // reported... just ignore it.
- return;
- }
- old.binder.unlinkToDeath(old.deathMonitor, 0);
- }
-
- if (mActivityThread != null) {
- mActivityThread.post(new RunConnection(name, service, 1));
- } else {
- doDeath(name, service);
- }
- }
-
- public void doConnected(ComponentName name, IBinder service) {
- ConnectionInfo old;
- ConnectionInfo info;
-
- synchronized (this) {
- old = mActiveConnections.get(name);
- if (old != null && old.binder == service) {
- // Huh, already have this one. Oh well!
- return;
- }
-
- if (service != null) {
- // A new service is being connected... set it all up.
- mDied = false;
- info = new ConnectionInfo();
- info.binder = service;
- info.deathMonitor = new DeathMonitor(name, service);
- try {
- service.linkToDeath(info.deathMonitor, 0);
- mActiveConnections.put(name, info);
- } catch (RemoteException e) {
- // This service was dead before we got it... just
- // don't do anything with it.
- mActiveConnections.remove(name);
- return;
- }
-
- } else {
- // The named service is being disconnected... clean up.
- mActiveConnections.remove(name);
- }
-
- if (old != null) {
- old.binder.unlinkToDeath(old.deathMonitor, 0);
- }
- }
-
- // If there was an old service, it is not disconnected.
- if (old != null) {
- mConnection.onServiceDisconnected(name);
- }
- // If there is a new service, it is now connected.
- if (service != null) {
- mConnection.onServiceConnected(name, service);
- }
- }
-
- public void doDeath(ComponentName name, IBinder service) {
- mConnection.onServiceDisconnected(name);
- }
-
- private final class RunConnection implements Runnable {
- RunConnection(ComponentName name, IBinder service, int command) {
- mName = name;
- mService = service;
- mCommand = command;
- }
-
- public void run() {
- if (mCommand == 0) {
- doConnected(mName, mService);
- } else if (mCommand == 1) {
- doDeath(mName, mService);
- }
- }
-
- final ComponentName mName;
- final IBinder mService;
- final int mCommand;
- }
-
- private final class DeathMonitor implements IBinder.DeathRecipient
- {
- DeathMonitor(ComponentName name, IBinder service) {
- mName = name;
- mService = service;
- }
-
- public void binderDied() {
- death(mName, mService);
- }
-
- final ComponentName mName;
- final IBinder mService;
- }
- }
- }
-
- private static ContextImpl mSystemContext = null;
-
- private static final class ActivityRecord {
+ private static final class ActivityClientRecord {
IBinder token;
int ident;
Intent intent;
@@ -1309,10 +195,10 @@
boolean hideForNow;
Configuration newConfig;
Configuration createdConfig;
- ActivityRecord nextIdle;
+ ActivityClientRecord nextIdle;
ActivityInfo activityInfo;
- PackageInfo packageInfo;
+ LoadedApk packageInfo;
List<ResultInfo> pendingResults;
List<Intent> pendingIntents;
@@ -1320,7 +206,7 @@
boolean startsNotResumed;
boolean isForward;
- ActivityRecord() {
+ ActivityClientRecord() {
parent = null;
embeddedID = null;
paused = false;
@@ -1339,12 +225,12 @@
}
}
- private final class ProviderRecord implements IBinder.DeathRecipient {
+ private final class ProviderClientRecord implements IBinder.DeathRecipient {
final String mName;
final IContentProvider mProvider;
final ContentProvider mLocalProvider;
- ProviderRecord(String name, IContentProvider provider,
+ ProviderClientRecord(String name, IContentProvider provider,
ContentProvider localProvider) {
mName = name;
mProvider = provider;
@@ -1421,7 +307,7 @@
}
private static final class AppBindData {
- PackageInfo info;
+ LoadedApk info;
String processName;
ApplicationInfo appInfo;
List<ProviderInfo> providers;
@@ -1511,7 +397,7 @@
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) {
- ActivityRecord r = new ActivityRecord();
+ ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
@@ -1531,7 +417,7 @@
public final void scheduleRelaunchActivity(IBinder token,
List<ResultInfo> pendingResults, List<Intent> pendingNewIntents,
int configChanges, boolean notResumed, Configuration config) {
- ActivityRecord r = new ActivityRecord();
+ ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.pendingResults = pendingResults;
@@ -2028,14 +914,14 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {
- ActivityRecord r = (ActivityRecord)msg.obj;
+ ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo);
handleLaunchActivity(r, null);
} break;
case RELAUNCH_ACTIVITY: {
- ActivityRecord r = (ActivityRecord)msg.obj;
+ ActivityClientRecord r = (ActivityClientRecord)msg.obj;
handleRelaunchActivity(r, msg.arg1);
} break;
case PAUSE_ACTIVITY:
@@ -2157,11 +1043,11 @@
private final class Idler implements MessageQueue.IdleHandler {
public final boolean queueIdle() {
- ActivityRecord a = mNewActivities;
+ ActivityClientRecord a = mNewActivities;
if (a != null) {
mNewActivities = null;
IActivityManager am = ActivityManagerNative.getDefault();
- ActivityRecord prev;
+ ActivityClientRecord prev;
do {
if (localLOGV) Slog.v(
TAG, "Reporting idle of " + a +
@@ -2217,71 +1103,132 @@
}
}
- static IPackageManager sPackageManager;
+ public static final ActivityThread currentActivityThread() {
+ return (ActivityThread)sThreadLocal.get();
+ }
- final ApplicationThread mAppThread = new ApplicationThread();
- final Looper mLooper = Looper.myLooper();
- final H mH = new H();
- final HashMap<IBinder, ActivityRecord> mActivities
- = new HashMap<IBinder, ActivityRecord>();
- // List of new activities (via ActivityRecord.nextIdle) that should
- // be reported when next we idle.
- ActivityRecord mNewActivities = null;
- // Number of activities that are currently visible on-screen.
- int mNumVisibleActivities = 0;
- final HashMap<IBinder, Service> mServices
- = new HashMap<IBinder, Service>();
- AppBindData mBoundApplication;
- Configuration mConfiguration;
- Configuration mResConfiguration;
- Application mInitialApplication;
- final ArrayList<Application> mAllApplications
- = new ArrayList<Application>();
- // set of instantiated backup agents, keyed by package name
- final HashMap<String, BackupAgent> mBackupAgents = new HashMap<String, BackupAgent>();
- static final ThreadLocal sThreadLocal = new ThreadLocal();
- Instrumentation mInstrumentation;
- String mInstrumentationAppDir = null;
- String mInstrumentationAppPackage = null;
- String mInstrumentedAppDir = null;
- boolean mSystemThread = false;
- boolean mJitEnabled = false;
+ public static final String currentPackageName() {
+ ActivityThread am = currentActivityThread();
+ return (am != null && am.mBoundApplication != null)
+ ? am.mBoundApplication.processName : null;
+ }
- // These can be accessed by multiple threads; mPackages is the lock.
- // XXX For now we keep around information about all packages we have
- // seen, not removing entries from this map.
- final HashMap<String, WeakReference<PackageInfo>> mPackages
- = new HashMap<String, WeakReference<PackageInfo>>();
- final HashMap<String, WeakReference<PackageInfo>> mResourcePackages
- = new HashMap<String, WeakReference<PackageInfo>>();
- Display mDisplay = null;
- DisplayMetrics mDisplayMetrics = null;
- final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
- = new HashMap<ResourcesKey, WeakReference<Resources> >();
- final ArrayList<ActivityRecord> mRelaunchingActivities
- = new ArrayList<ActivityRecord>();
- Configuration mPendingConfiguration = null;
+ public static final Application currentApplication() {
+ ActivityThread am = currentActivityThread();
+ return am != null ? am.mInitialApplication : null;
+ }
- // The lock of mProviderMap protects the following variables.
- final HashMap<String, ProviderRecord> mProviderMap
- = new HashMap<String, ProviderRecord>();
- final HashMap<IBinder, ProviderRefCount> mProviderRefCountMap
- = new HashMap<IBinder, ProviderRefCount>();
- final HashMap<IBinder, ProviderRecord> mLocalProviders
- = new HashMap<IBinder, ProviderRecord>();
+ public static IPackageManager getPackageManager() {
+ if (sPackageManager != null) {
+ //Slog.v("PackageManager", "returning cur default = " + sPackageManager);
+ return sPackageManager;
+ }
+ IBinder b = ServiceManager.getService("package");
+ //Slog.v("PackageManager", "default service binder = " + b);
+ sPackageManager = IPackageManager.Stub.asInterface(b);
+ //Slog.v("PackageManager", "default service = " + sPackageManager);
+ return sPackageManager;
+ }
- final GcIdler mGcIdler = new GcIdler();
- boolean mGcIdlerScheduled = false;
+ DisplayMetrics getDisplayMetricsLocked(boolean forceUpdate) {
+ if (mDisplayMetrics != null && !forceUpdate) {
+ return mDisplayMetrics;
+ }
+ if (mDisplay == null) {
+ WindowManager wm = WindowManagerImpl.getDefault();
+ mDisplay = wm.getDefaultDisplay();
+ }
+ DisplayMetrics metrics = mDisplayMetrics = new DisplayMetrics();
+ mDisplay.getMetrics(metrics);
+ //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
+ // + metrics.heightPixels + " den=" + metrics.density
+ // + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
+ return metrics;
+ }
- public final PackageInfo getPackageInfo(String packageName, int flags) {
+ /**
+ * Creates the top level Resources for applications with the given compatibility info.
+ *
+ * @param resDir the resource directory.
+ * @param compInfo the compability info. It will use the default compatibility info when it's
+ * null.
+ */
+ Resources getTopLevelResources(String resDir, CompatibilityInfo compInfo) {
+ ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale);
+ Resources r;
synchronized (mPackages) {
- WeakReference<PackageInfo> ref;
+ // Resources is app scale dependent.
+ if (false) {
+ Slog.w(TAG, "getTopLevelResources: " + resDir + " / "
+ + compInfo.applicationScale);
+ }
+ WeakReference<Resources> wr = mActiveResources.get(key);
+ r = wr != null ? wr.get() : null;
+ //if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
+ if (r != null && r.getAssets().isUpToDate()) {
+ if (false) {
+ Slog.w(TAG, "Returning cached resources " + r + " " + resDir
+ + ": appScale=" + r.getCompatibilityInfo().applicationScale);
+ }
+ return r;
+ }
+ }
+
+ //if (r != null) {
+ // Slog.w(TAG, "Throwing away out-of-date resources!!!! "
+ // + r + " " + resDir);
+ //}
+
+ AssetManager assets = new AssetManager();
+ if (assets.addAssetPath(resDir) == 0) {
+ return null;
+ }
+
+ //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
+ DisplayMetrics metrics = getDisplayMetricsLocked(false);
+ r = new Resources(assets, metrics, getConfiguration(), compInfo);
+ if (false) {
+ Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
+ + r.getConfiguration() + " appScale="
+ + r.getCompatibilityInfo().applicationScale);
+ }
+
+ synchronized (mPackages) {
+ WeakReference<Resources> wr = mActiveResources.get(key);
+ Resources existing = wr != null ? wr.get() : null;
+ if (existing != null && existing.getAssets().isUpToDate()) {
+ // Someone else already created the resources while we were
+ // unlocked; go ahead and use theirs.
+ r.getAssets().close();
+ return existing;
+ }
+
+ // XXX need to remove entries when weak references go away
+ mActiveResources.put(key, new WeakReference<Resources>(r));
+ return r;
+ }
+ }
+
+ /**
+ * Creates the top level resources for the given package.
+ */
+ Resources getTopLevelResources(String resDir, LoadedApk pkgInfo) {
+ return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo);
+ }
+
+ final Handler getHandler() {
+ return mH;
+ }
+
+ public final LoadedApk getPackageInfo(String packageName, int flags) {
+ synchronized (mPackages) {
+ WeakReference<LoadedApk> ref;
if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) {
ref = mPackages.get(packageName);
} else {
ref = mResourcePackages.get(packageName);
}
- PackageInfo packageInfo = ref != null ? ref.get() : null;
+ LoadedApk packageInfo = ref != null ? ref.get() : null;
//Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo);
//if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir
// + ": " + packageInfo.mResources.getAssets().isUpToDate());
@@ -2313,7 +1260,7 @@
return null;
}
- public final PackageInfo getPackageInfo(ApplicationInfo ai, int flags) {
+ public final LoadedApk getPackageInfo(ApplicationInfo ai, int flags) {
boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
boolean securityViolation = includeCode && ai.uid != 0
&& ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
@@ -2335,20 +1282,20 @@
return getPackageInfo(ai, null, securityViolation, includeCode);
}
- public final PackageInfo getPackageInfoNoCheck(ApplicationInfo ai) {
+ public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai) {
return getPackageInfo(ai, null, false, true);
}
- private final PackageInfo getPackageInfo(ApplicationInfo aInfo,
+ private final LoadedApk getPackageInfo(ApplicationInfo aInfo,
ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
synchronized (mPackages) {
- WeakReference<PackageInfo> ref;
+ WeakReference<LoadedApk> ref;
if (includeCode) {
ref = mPackages.get(aInfo.packageName);
} else {
ref = mResourcePackages.get(aInfo.packageName);
}
- PackageInfo packageInfo = ref != null ? ref.get() : null;
+ LoadedApk packageInfo = ref != null ? ref.get() : null;
if (packageInfo == null || (packageInfo.mResources != null
&& !packageInfo.mResources.getAssets().isUpToDate())) {
if (localLOGV) Slog.v(TAG, (includeCode ? "Loading code package "
@@ -2357,15 +1304,15 @@
? mBoundApplication.processName : null)
+ ")");
packageInfo =
- new PackageInfo(this, aInfo, this, baseLoader,
+ new LoadedApk(this, aInfo, this, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
if (includeCode) {
mPackages.put(aInfo.packageName,
- new WeakReference<PackageInfo>(packageInfo));
+ new WeakReference<LoadedApk>(packageInfo));
} else {
mResourcePackages.put(aInfo.packageName,
- new WeakReference<PackageInfo>(packageInfo));
+ new WeakReference<LoadedApk>(packageInfo));
}
}
return packageInfo;
@@ -2414,7 +1361,7 @@
if (mSystemContext == null) {
ContextImpl context =
ContextImpl.createSystemContext(this);
- PackageInfo info = new PackageInfo(this, "android", context, null);
+ LoadedApk info = new LoadedApk(this, "android", context, null);
context.init(info, null, this);
context.getResources().updateConfiguration(
getConfiguration(), getDisplayMetricsLocked(false));
@@ -2429,7 +1376,7 @@
public void installSystemApplicationInfo(ApplicationInfo info) {
synchronized (this) {
ContextImpl context = getSystemContext();
- context.init(new PackageInfo(this, "android", context, info), null, this);
+ context.init(new LoadedApk(this, "android", context, info), null, this);
}
}
@@ -2481,7 +1428,7 @@
public final Activity startActivityNow(Activity parent, String id,
Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
Object lastNonConfigurationInstance) {
- ActivityRecord r = new ActivityRecord();
+ ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = 0;
r.intent = intent;
@@ -2552,7 +1499,7 @@
queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci);
}
- private final Activity performLaunchActivity(ActivityRecord r, Intent customIntent) {
+ private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
ActivityInfo aInfo = r.activityInfo;
@@ -2671,7 +1618,7 @@
return activity;
}
- private final void handleLaunchActivity(ActivityRecord r, Intent customIntent) {
+ private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
@@ -2731,7 +1678,7 @@
}
}
- private final void deliverNewIntents(ActivityRecord r,
+ private final void deliverNewIntents(ActivityClientRecord r,
List<Intent> intents) {
final int N = intents.size();
for (int i=0; i<N; i++) {
@@ -2743,7 +1690,7 @@
public final void performNewIntents(IBinder token,
List<Intent> intents) {
- ActivityRecord r = mActivities.get(token);
+ ActivityClientRecord r = mActivities.get(token);
if (r != null) {
final boolean resumed = !r.paused;
if (resumed) {
@@ -2767,7 +1714,7 @@
String component = data.intent.getComponent().getClassName();
- PackageInfo packageInfo = getPackageInfoNoCheck(
+ LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo);
IActivityManager mgr = ActivityManagerNative.getDefault();
@@ -2851,7 +1798,7 @@
unscheduleGcIdler();
// instantiate the BackupAgent class named in the manifest
- PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo);
+ LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo);
String packageName = packageInfo.mPackageName;
if (mBackupAgents.get(packageName) != null) {
Slog.d(TAG, "BackupAgent " + " for " + packageName
@@ -2913,7 +1860,7 @@
private final void handleDestroyBackupAgent(CreateBackupAgentData data) {
if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
- PackageInfo packageInfo = getPackageInfoNoCheck(data.appInfo);
+ LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo);
String packageName = packageInfo.mPackageName;
BackupAgent agent = mBackupAgents.get(packageName);
if (agent != null) {
@@ -2934,7 +1881,7 @@
// we are back active so skip it.
unscheduleGcIdler();
- PackageInfo packageInfo = getPackageInfoNoCheck(
+ LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo);
Service service = null;
try {
@@ -3098,9 +2045,9 @@
//Slog.i(TAG, "Running services: " + mServices);
}
- public final ActivityRecord performResumeActivity(IBinder token,
+ public final ActivityClientRecord performResumeActivity(IBinder token,
boolean clearHide) {
- ActivityRecord r = mActivities.get(token);
+ ActivityClientRecord r = mActivities.get(token);
if (localLOGV) Slog.v(TAG, "Performing resume of " + r
+ " finished=" + r.activity.mFinished);
if (r != null && !r.activity.mFinished) {
@@ -3142,7 +2089,7 @@
// we are back active so skip it.
unscheduleGcIdler();
- ActivityRecord r = performResumeActivity(token, clearHide);
+ ActivityClientRecord r = performResumeActivity(token, clearHide);
if (r != null) {
final Activity a = r.activity;
@@ -3241,7 +2188,7 @@
private int mThumbnailWidth = -1;
private int mThumbnailHeight = -1;
- private final Bitmap createThumbnailBitmap(ActivityRecord r) {
+ private final Bitmap createThumbnailBitmap(ActivityClientRecord r) {
Bitmap thumbnail = null;
try {
int w = mThumbnailWidth;
@@ -3279,7 +2226,7 @@
private final void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges) {
- ActivityRecord r = mActivities.get(token);
+ ActivityClientRecord r = mActivities.get(token);
if (r != null) {
//Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
if (userLeaving) {
@@ -3297,17 +2244,17 @@
}
}
- final void performUserLeavingActivity(ActivityRecord r) {
+ final void performUserLeavingActivity(ActivityClientRecord r) {
mInstrumentation.callActivityOnUserLeaving(r.activity);
}
final Bundle performPauseActivity(IBinder token, boolean finished,
boolean saveState) {
- ActivityRecord r = mActivities.get(token);
+ ActivityClientRecord r = mActivities.get(token);
return r != null ? performPauseActivity(r, finished, saveState) : null;
}
- final Bundle performPauseActivity(ActivityRecord r, boolean finished,
+ final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
boolean saveState) {
if (r.paused) {
if (r.activity.mFinished) {
@@ -3358,7 +2305,7 @@
}
final void performStopActivity(IBinder token) {
- ActivityRecord r = mActivities.get(token);
+ ActivityClientRecord r = mActivities.get(token);
performStopActivityInner(r, null, false);
}
@@ -3374,7 +2321,7 @@
}
}
- private final void performStopActivityInner(ActivityRecord r,
+ private final void performStopActivityInner(ActivityClientRecord r,
StopInfo info, boolean keepShown) {
if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
if (r != null) {
@@ -3425,7 +2372,7 @@
}
}
- private final void updateVisibility(ActivityRecord r, boolean show) {
+ private final void updateVisibility(ActivityClientRecord r, boolean show) {
View v = r.activity.mDecor;
if (v != null) {
if (show) {
@@ -3453,7 +2400,7 @@
}
private final void handleStopActivity(IBinder token, boolean show, int configChanges) {
- ActivityRecord r = mActivities.get(token);
+ ActivityClientRecord r = mActivities.get(token);
r.activity.mConfigChangeFlags |= configChanges;
StopInfo info = new StopInfo();
@@ -3474,7 +2421,7 @@
}
final void performRestartActivity(IBinder token) {
- ActivityRecord r = mActivities.get(token);
+ ActivityClientRecord r = mActivities.get(token);
if (r.stopped) {
r.activity.performRestart();
r.stopped = false;
@@ -3482,7 +2429,7 @@
}
private final void handleWindowVisibility(IBinder token, boolean show) {
- ActivityRecord r = mActivities.get(token);
+ ActivityClientRecord r = mActivities.get(token);
if (!show && !r.stopped) {
performStopActivityInner(r, null, show);
} else if (show && r.stopped) {
@@ -3500,7 +2447,7 @@
}
}
- private final void deliverResults(ActivityRecord r, List<ResultInfo> results) {
+ private final void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
final int N = results.size();
for (int i=0; i<N; i++) {
ResultInfo ri = results.get(i);
@@ -3524,7 +2471,7 @@
}
private final void handleSendResult(ResultData res) {
- ActivityRecord r = mActivities.get(res.token);
+ ActivityClientRecord r = mActivities.get(res.token);
if (DEBUG_RESULTS) Slog.v(TAG, "Handling send result to " + r);
if (r != null) {
final boolean resumed = !r.paused;
@@ -3563,13 +2510,13 @@
}
}
- public final ActivityRecord performDestroyActivity(IBinder token, boolean finishing) {
+ public final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing) {
return performDestroyActivity(token, finishing, 0, false);
}
- private final ActivityRecord performDestroyActivity(IBinder token, boolean finishing,
+ private final ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance) {
- ActivityRecord r = mActivities.get(token);
+ ActivityClientRecord r = mActivities.get(token);
if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
if (r != null) {
r.activity.mConfigChangeFlags |= configChanges;
@@ -3672,7 +2619,7 @@
private final void handleDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance) {
- ActivityRecord r = performDestroyActivity(token, finishing,
+ ActivityClientRecord r = performDestroyActivity(token, finishing,
configChanges, getNonConfigInstance);
if (r != null) {
WindowManager wm = r.activity.getWindowManager();
@@ -3713,7 +2660,7 @@
}
}
- private final void handleRelaunchActivity(ActivityRecord tmp, int configChanges) {
+ private final void handleRelaunchActivity(ActivityClientRecord tmp, int configChanges) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
@@ -3732,7 +2679,7 @@
IBinder token = tmp.token;
tmp = null;
for (int i=0; i<N; i++) {
- ActivityRecord r = mRelaunchingActivities.get(i);
+ ActivityClientRecord r = mRelaunchingActivities.get(i);
if (r.token == token) {
tmp = r;
mRelaunchingActivities.remove(i);
@@ -3774,7 +2721,7 @@
handleConfigurationChanged(changedConfig);
}
- ActivityRecord r = mActivities.get(tmp.token);
+ ActivityClientRecord r = mActivities.get(tmp.token);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handling relaunch of " + r);
if (r == null) {
return;
@@ -3818,7 +2765,7 @@
}
private final void handleRequestThumbnail(IBinder token) {
- ActivityRecord r = mActivities.get(token);
+ ActivityClientRecord r = mActivities.get(token);
Bitmap thumbnail = createThumbnailBitmap(r);
CharSequence description = null;
try {
@@ -3845,9 +2792,9 @@
= new ArrayList<ComponentCallbacks>();
if (mActivities.size() > 0) {
- Iterator<ActivityRecord> it = mActivities.values().iterator();
+ Iterator<ActivityClientRecord> it = mActivities.values().iterator();
while (it.hasNext()) {
- ActivityRecord ar = it.next();
+ ActivityClientRecord ar = it.next();
Activity a = ar.activity;
if (a != null) {
if (!ar.activity.mFinished && (allActivities ||
@@ -3876,7 +2823,7 @@
}
synchronized (mProviderMap) {
if (mLocalProviders.size() > 0) {
- Iterator<ProviderRecord> it = mLocalProviders.values().iterator();
+ Iterator<ProviderClientRecord> it = mLocalProviders.values().iterator();
while (it.hasNext()) {
callbacks.add(it.next().mLocalProvider);
}
@@ -4022,7 +2969,7 @@
}
final void handleActivityConfigurationChanged(IBinder token) {
- ActivityRecord r = mActivities.get(token);
+ ActivityClientRecord r = mActivities.get(token);
if (r == null || r.activity == null) {
return;
}
@@ -4059,7 +3006,7 @@
for (int i=packages.length-1; i>=0; i--) {
//Slog.i(TAG, "Cleaning old package: " + packages[i]);
if (!hasPkgInfo) {
- WeakReference<PackageInfo> ref;
+ WeakReference<LoadedApk> ref;
ref = mPackages.get(packages[i]);
if (ref != null && ref.get() != null) {
hasPkgInfo = true;
@@ -4204,7 +3151,7 @@
instrApp.sourceDir = ii.sourceDir;
instrApp.publicSourceDir = ii.publicSourceDir;
instrApp.dataDir = ii.dataDir;
- PackageInfo pi = getPackageInfo(instrApp,
+ LoadedApk pi = getPackageInfo(instrApp,
appContext.getClassLoader(), false, true);
ContextImpl instrContext = new ContextImpl();
instrContext.init(pi, null, this);
@@ -4315,7 +3262,7 @@
private final IContentProvider getProvider(Context context, String name) {
synchronized(mProviderMap) {
- final ProviderRecord pr = mProviderMap.get(name);
+ final ProviderClientRecord pr = mProviderMap.get(name);
if (pr != null) {
return pr.mProvider;
}
@@ -4426,9 +3373,9 @@
String name = null;
// remove the provider from mProviderMap
- Iterator<ProviderRecord> iter = mProviderMap.values().iterator();
+ Iterator<ProviderClientRecord> iter = mProviderMap.values().iterator();
while (iter.hasNext()) {
- ProviderRecord pr = iter.next();
+ ProviderClientRecord pr = iter.next();
IBinder myBinder = pr.mProvider.asBinder();
if (myBinder == providerBinder) {
//find if its published by this process itself
@@ -4453,10 +3400,10 @@
final void removeDeadProvider(String name, IContentProvider provider) {
synchronized(mProviderMap) {
- ProviderRecord pr = mProviderMap.get(name);
+ ProviderClientRecord pr = mProviderMap.get(name);
if (pr.mProvider.asBinder() == provider.asBinder()) {
Slog.i(TAG, "Removing dead content provider: " + name);
- ProviderRecord removed = mProviderMap.remove(name);
+ ProviderClientRecord removed = mProviderMap.remove(name);
if (removed != null) {
removed.mProvider.asBinder().unlinkToDeath(removed, 0);
}
@@ -4465,10 +3412,10 @@
}
final void removeDeadProviderLocked(String name, IContentProvider provider) {
- ProviderRecord pr = mProviderMap.get(name);
+ ProviderClientRecord pr = mProviderMap.get(name);
if (pr.mProvider.asBinder() == provider.asBinder()) {
Slog.i(TAG, "Removing dead content provider: " + name);
- ProviderRecord removed = mProviderMap.remove(name);
+ ProviderClientRecord removed = mProviderMap.remove(name);
if (removed != null) {
removed.mProvider.asBinder().unlinkToDeath(removed, 0);
}
@@ -4536,7 +3483,7 @@
// Cache the pointer for the remote provider.
String names[] = PATTERN_SEMICOLON.split(info.authority);
for (int i=0; i<names.length; i++) {
- ProviderRecord pr = new ProviderRecord(names[i], provider,
+ ProviderClientRecord pr = new ProviderClientRecord(names[i], provider,
localProvider);
try {
provider.asBinder().linkToDeath(pr, 0);
@@ -4547,7 +3494,7 @@
}
if (localProvider != null) {
mLocalProviders.put(provider.asBinder(),
- new ProviderRecord(null, provider, localProvider));
+ new ProviderClientRecord(null, provider, localProvider));
}
}