Merge "Various fixes and improvements in audio effects implementation" into gingerbread
diff --git a/api/current.xml b/api/current.xml
index f8c644e..8cc95ab 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -21750,6 +21750,17 @@
visibility="public"
>
</field>
+<field name="FLAG_HEAVY_WEIGHT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="IMPORTANCE_BACKGROUND"
type="int"
transient="false"
@@ -21860,6 +21871,16 @@
visibility="public"
>
</field>
+<field name="flags"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="importance"
type="int"
transient="false"
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 80d0d2b..33696f4 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -1,5 +1,3 @@
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -72,5 +70,3 @@
LOCAL_MODULE:= audioloop
include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 7f95bf5..eb7520f 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -717,9 +717,24 @@
*/
public int uid;
+ /**
+ * All packages that have been loaded into the process.
+ */
public String pkgList[];
/**
+ * Constant for {@link #flags}: this is a heavy-weight process,
+ * meaning it will not be killed while in the background.
+ */
+ public static final int FLAG_HEAVY_WEIGHT = 1<<0;
+
+ /**
+ * Flags of information. May be any of
+ * {@link #FLAG_HEAVY_WEIGHT}.
+ */
+ public int flags;
+
+ /**
* Constant for {@link #importance}: this process is running the
* foreground UI.
*/
@@ -846,6 +861,7 @@
dest.writeInt(pid);
dest.writeInt(uid);
dest.writeStringArray(pkgList);
+ dest.writeInt(this.flags);
dest.writeInt(importance);
dest.writeInt(lru);
dest.writeInt(importanceReasonCode);
@@ -858,6 +874,7 @@
pid = source.readInt();
uid = source.readInt();
pkgList = source.readStringArray();
+ flags = source.readInt();
importance = source.readInt();
lru = source.readInt();
importanceReasonCode = source.readInt();
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 63b2f08..e56fee9 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1293,6 +1293,17 @@
return true;
}
+ case CRASH_APPLICATION_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ int uid = data.readInt();
+ int initialPid = data.readInt();
+ String packageName = data.readString();
+ String message = data.readString();
+ crashApplication(uid, initialPid, packageName, message);
+ reply.writeNoException();
+ return true;
+ }
+
}
return super.onTransact(code, data, reply, flags);
@@ -2867,5 +2878,20 @@
return res;
}
+ public void crashApplication(int uid, int initialPid, String packageName,
+ String message) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeInt(uid);
+ data.writeInt(initialPid);
+ data.writeString(packageName);
+ data.writeString(message);
+ mRemote.transact(CRASH_APPLICATION_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 0ce790e..03bb858 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,24 +93,18 @@
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);
}
}
+final class RemoteServiceException extends AndroidRuntimeException {
+ public RemoteServiceException(String msg) {
+ super(msg);
+ }
+}
+
/**
* This manages the execution of the main thread in an
* application process, scheduling and executing activities,
@@ -125,10 +114,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 +127,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 +201,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 +212,7 @@
boolean startsNotResumed;
boolean isForward;
- ActivityRecord() {
+ ActivityClientRecord() {
parent = null;
embeddedID = null;
paused = false;
@@ -1339,12 +231,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 +313,7 @@
}
private static final class AppBindData {
- PackageInfo info;
+ LoadedApk info;
String processName;
ApplicationInfo appInfo;
List<ProviderInfo> providers;
@@ -1511,7 +403,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 +423,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;
@@ -1758,6 +650,10 @@
public void dispatchPackageBroadcast(int cmd, String[] packages) {
queueOrSendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
}
+
+ public void scheduleCrash(String msg) {
+ queueOrSendMessage(H.SCHEDULE_CRASH, msg);
+ }
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -1984,6 +880,7 @@
public static final int REMOVE_PROVIDER = 131;
public static final int ENABLE_JIT = 132;
public static final int DISPATCH_PACKAGE_BROADCAST = 133;
+ public static final int SCHEDULE_CRASH = 134;
String codeToString(int code) {
if (localLOGV) {
switch (code) {
@@ -2021,6 +918,7 @@
case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
case ENABLE_JIT: return "ENABLE_JIT";
case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
+ case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
}
}
return "(unknown)";
@@ -2028,14 +926,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:
@@ -2144,6 +1042,8 @@
case DISPATCH_PACKAGE_BROADCAST:
handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
break;
+ case SCHEDULE_CRASH:
+ throw new RemoteServiceException((String)msg.obj);
}
}
@@ -2157,11 +1057,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 +1117,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 +1274,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 +1296,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 +1318,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 +1375,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 +1390,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 +1442,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 +1513,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 +1632,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 +1692,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 +1704,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 +1728,7 @@
String component = data.intent.getComponent().getClassName();
- PackageInfo packageInfo = getPackageInfoNoCheck(
+ LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo);
IActivityManager mgr = ActivityManagerNative.getDefault();
@@ -2851,7 +1812,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 +1874,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 +1895,7 @@
// we are back active so skip it.
unscheduleGcIdler();
- PackageInfo packageInfo = getPackageInfoNoCheck(
+ LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo);
Service service = null;
try {
@@ -3098,9 +2059,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 +2103,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 +2202,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 +2240,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 +2258,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 +2319,7 @@
}
final void performStopActivity(IBinder token) {
- ActivityRecord r = mActivities.get(token);
+ ActivityClientRecord r = mActivities.get(token);
performStopActivityInner(r, null, false);
}
@@ -3374,7 +2335,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 +2386,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 +2414,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 +2435,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 +2443,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 +2461,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 +2485,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 +2524,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 +2633,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 +2674,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 +2693,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 +2735,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 +2779,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 +2806,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 +2837,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 +2983,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 +3020,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 +3165,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 +3276,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 +3387,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 +3414,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 +3426,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 +3497,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 +3508,7 @@
}
if (localProvider != null) {
mLocalProviders.put(provider.asBinder(),
- new ProviderRecord(null, provider, localProvider));
+ new ProviderClientRecord(null, provider, localProvider));
}
}
diff --git a/core/java/android/app/AppGlobals.java b/core/java/android/app/AppGlobals.java
new file mode 100644
index 0000000..9a39129
--- /dev/null
+++ b/core/java/android/app/AppGlobals.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.content.pm.IPackageManager;
+
+/**
+ * Special private access for certain globals related to a process.
+ * @hide
+ */
+public class AppGlobals {
+ /**
+ * Return the first Application object made in the process.
+ * NOTE: Only works on the main thread.
+ */
+ public static Application getInitialApplication() {
+ return ActivityThread.currentApplication();
+ }
+
+ /**
+ * Return the package name of the first .apk loaded into the process.
+ * NOTE: Only works on the main thread.
+ */
+ public static String getInitialPackage() {
+ return ActivityThread.currentPackageName();
+ }
+
+ /**
+ * Return the raw interface to the package manager.
+ * @return
+ */
+ public static IPackageManager getPackageManager() {
+ return ActivityThread.getPackageManager();
+ }
+}
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index da26a78..360959d 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -402,6 +402,14 @@
dispatchPackageBroadcast(cmd, packages);
return true;
}
+
+ case SCHEDULE_CRASH_TRANSACTION:
+ {
+ data.enforceInterface(IApplicationThread.descriptor);
+ String msg = data.readString();
+ scheduleCrash(msg);
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -826,5 +834,15 @@
data.recycle();
}
+
+ public void scheduleCrash(String msg) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken(IApplicationThread.descriptor);
+ data.writeString(msg);
+ mRemote.transact(SCHEDULE_CRASH_TRANSACTION, data, null,
+ IBinder.FLAG_ONEWAY);
+ data.recycle();
+
+ }
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index bcdfe59..fc9bcf7 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -173,7 +173,7 @@
new HashMap<File, SharedPreferencesImpl>();
private AudioManager mAudioManager;
- /*package*/ ActivityThread.PackageInfo mPackageInfo;
+ /*package*/ LoadedApk mPackageInfo;
private Resources mResources;
/*package*/ ActivityThread mMainThread;
private Context mOuterContext;
@@ -696,7 +696,7 @@
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
- rd = new ActivityThread.PackageInfo.ReceiverDispatcher(
+ rd = new LoadedApk.ReceiverDispatcher(
resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
}
}
@@ -739,7 +739,7 @@
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
- rd = new ActivityThread.PackageInfo.ReceiverDispatcher(
+ rd = new LoadedApk.ReceiverDispatcher(
resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
}
}
@@ -795,7 +795,7 @@
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
- rd = new ActivityThread.PackageInfo.ReceiverDispatcher(
+ rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
@@ -1425,7 +1425,7 @@
return new ContextImpl(mMainThread.getSystemContext());
}
- ActivityThread.PackageInfo pi =
+ LoadedApk pi =
mMainThread.getPackageInfo(packageName, flags);
if (pi != null) {
ContextImpl c = new ContextImpl();
@@ -1492,12 +1492,12 @@
mOuterContext = this;
}
- final void init(ActivityThread.PackageInfo packageInfo,
+ final void init(LoadedApk packageInfo,
IBinder activityToken, ActivityThread mainThread) {
init(packageInfo, activityToken, mainThread, null);
}
- final void init(ActivityThread.PackageInfo packageInfo,
+ final void init(LoadedApk packageInfo,
IBinder activityToken, ActivityThread mainThread,
Resources container) {
mPackageInfo = packageInfo;
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 3a86ead..bf02d5a 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -316,6 +316,9 @@
public boolean isImmersive(IBinder token) throws RemoteException;
public boolean isTopActivityImmersive() throws RemoteException;
+ public void crashApplication(int uid, int initialPid, String packageName,
+ String message) throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -531,4 +534,5 @@
int IS_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+110;
int SET_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+111;
int IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+112;
+ int CRASH_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+113;
}
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index c917e81..ffb8651 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -103,6 +103,7 @@
static final int PACKAGE_REMOVED = 0;
static final int EXTERNAL_STORAGE_UNAVAILABLE = 1;
void dispatchPackageBroadcast(int cmd, String[] packages) throws RemoteException;
+ void scheduleCrash(String msg) throws RemoteException;
String descriptor = "android.app.IApplicationThread";
@@ -139,4 +140,5 @@
int GET_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+31;
int SCHEDULE_SUICIDE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+32;
int DISPATCH_PACKAGE_BROADCAST_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+33;
+ int SCHEDULE_CRASH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+34;
}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
new file mode 100644
index 0000000..0f98152
--- /dev/null
+++ b/core/java/android/app/LoadedApk.java
@@ -0,0 +1,1103 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import com.android.internal.util.ArrayUtils;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.IIntentReceiver;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.res.AssetManager;
+import android.content.res.CompatibilityInfo;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.util.AndroidRuntimeException;
+import android.util.Slog;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.ref.WeakReference;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+
+final class IntentReceiverLeaked extends AndroidRuntimeException {
+ public IntentReceiverLeaked(String msg) {
+ super(msg);
+ }
+}
+
+final class ServiceConnectionLeaked extends AndroidRuntimeException {
+ public ServiceConnectionLeaked(String msg) {
+ super(msg);
+ }
+}
+
+/**
+ * Local state maintained about a currently loaded .apk.
+ * @hide
+ */
+final class LoadedApk {
+
+ private final ActivityThread mActivityThread;
+ private final ApplicationInfo mApplicationInfo;
+ 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;
+ Resources mResources;
+ private ClassLoader mClassLoader;
+ private Application mApplication;
+ CompatibilityInfo mCompatibilityInfo;
+
+ private final HashMap<Context, HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mReceivers
+ = new HashMap<Context, HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
+ private final HashMap<Context, HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
+ = new HashMap<Context, HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
+ private final HashMap<Context, HashMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
+ = new HashMap<Context, HashMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
+ private final HashMap<Context, HashMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
+ = new HashMap<Context, HashMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
+
+ int mClientCount = 0;
+
+ Application getApplication() {
+ return mApplication;
+ }
+
+ public LoadedApk(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 (ActivityThread.mSystemContext == null) {
+ ActivityThread.mSystemContext =
+ ContextImpl.createSystemContext(mainThread);
+ ActivityThread.mSystemContext.getResources().updateConfiguration(
+ mainThread.getConfiguration(),
+ mainThread.getDisplayMetricsLocked(false));
+ //Slog.i(TAG, "Created system resources "
+ // + mSystemContext.getResources() + ": "
+ // + mSystemContext.getResources().getConfiguration());
+ }
+ mClassLoader = ActivityThread.mSystemContext.getClassLoader();
+ mResources = ActivityThread.mSystemContext.getResources();
+ }
+ }
+
+ public LoadedApk(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 = ActivityThread.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 (ActivityThread.localLOGV) Slog.v(ActivityThread.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 = ActivityThread.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(ActivityThread.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, LoadedApk.ReceiverDispatcher> rmap =
+ mReceivers.remove(context);
+ if (rmap != null) {
+ Iterator<LoadedApk.ReceiverDispatcher> it = rmap.values().iterator();
+ while (it.hasNext()) {
+ LoadedApk.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(ActivityThread.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, LoadedApk.ServiceDispatcher> smap =
+ mServices.remove(context);
+ if (smap != null) {
+ Iterator<LoadedApk.ServiceDispatcher> it = smap.values().iterator();
+ while (it.hasNext()) {
+ LoadedApk.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(ActivityThread.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) {
+ LoadedApk.ReceiverDispatcher rd = null;
+ HashMap<BroadcastReceiver, LoadedApk.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, LoadedApk.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, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);
+ LoadedApk.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, LoadedApk.ReceiverDispatcher> holder
+ = mUnregisteredReceivers.get(context);
+ if (holder == null) {
+ holder = new HashMap<BroadcastReceiver, LoadedApk.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, LoadedApk.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<LoadedApk.ReceiverDispatcher> mDispatcher;
+ final LoadedApk.ReceiverDispatcher mStrongRef;
+
+ InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
+ mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
+ mStrongRef = strong ? rd : null;
+ }
+ public void performReceive(Intent intent, int resultCode,
+ String data, Bundle extras, boolean ordered, boolean sticky) {
+ LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
+ if (ActivityThread.DEBUG_BROADCAST) {
+ int seq = intent.getIntExtra("seq", -1);
+ Slog.i(ActivityThread.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 (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
+ "Finishing broadcast to unregistered receiver");
+ IActivityManager mgr = ActivityManagerNative.getDefault();
+ try {
+ mgr.finishReceiver(this, resultCode, data, extras, false);
+ } catch (RemoteException e) {
+ Slog.w(ActivityThread.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 (ActivityThread.DEBUG_BROADCAST) {
+ int seq = mCurIntent.getIntExtra("seq", -1);
+ Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
+ + " seq=" + seq + " to " + mReceiver);
+ Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered
+ + " mCurOrdered=" + mCurOrdered);
+ }
+
+ IActivityManager mgr = ActivityManagerNative.getDefault();
+ Intent intent = mCurIntent;
+ mCurIntent = null;
+
+ if (receiver == null) {
+ if (mRegistered && mCurOrdered) {
+ try {
+ if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.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 (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.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 (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.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 (ActivityThread.DEBUG_BROADCAST) {
+ int seq = intent.getIntExtra("seq", -1);
+ Slog.i(ActivityThread.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 (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.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) {
+ LoadedApk.ServiceDispatcher sd = null;
+ HashMap<ServiceConnection, LoadedApk.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, LoadedApk.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, LoadedApk.ServiceDispatcher> map
+ = mServices.get(context);
+ LoadedApk.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, LoadedApk.ServiceDispatcher> holder
+ = mUnboundServices.get(context);
+ if (holder == null) {
+ holder = new HashMap<ServiceConnection, LoadedApk.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, LoadedApk.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 ServiceDispatcher.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<LoadedApk.ServiceDispatcher> mDispatcher;
+
+ InnerConnection(LoadedApk.ServiceDispatcher sd) {
+ mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
+ }
+
+ public void connected(ComponentName name, IBinder service) throws RemoteException {
+ LoadedApk.ServiceDispatcher sd = mDispatcher.get();
+ if (sd != null) {
+ sd.connected(name, service);
+ }
+ }
+ }
+
+ private final HashMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections
+ = new HashMap<ComponentName, ServiceDispatcher.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<ServiceDispatcher.ConnectionInfo> it = mActiveConnections.values().iterator();
+ while (it.hasNext()) {
+ ServiceDispatcher.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) {
+ ServiceDispatcher.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) {
+ ServiceDispatcher.ConnectionInfo old;
+ ServiceDispatcher.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;
+ }
+ }
+}
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 88adabd..b2fc13f 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -237,7 +237,7 @@
v = mViews.get(appWidgetId);
}
if (v != null) {
- v.updateAppWidget(null, AppWidgetHostView.UPDATE_FLAGS_RESET);
+ v.resetAppWidget(appWidget);
}
}
@@ -247,7 +247,7 @@
v = mViews.get(appWidgetId);
}
if (v != null) {
- v.updateAppWidget(views, 0);
+ v.updateAppWidget(views);
}
}
}
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 5375193..b33b097 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -46,8 +46,6 @@
static final boolean LOGD = false;
static final boolean CROSSFADE = false;
- static final int UPDATE_FLAGS_RESET = 0x00000001;
-
static final int VIEW_MODE_NOINIT = 0;
static final int VIEW_MODE_CONTENT = 1;
static final int VIEW_MODE_ERROR = 2;
@@ -102,7 +100,7 @@
mAppWidgetId = appWidgetId;
mInfo = info;
}
-
+
public int getAppWidgetId() {
return mAppWidgetId;
}
@@ -148,21 +146,22 @@
}
/**
+ * Update the AppWidgetProviderInfo for this view, and reset it to the
+ * initial layout.
+ */
+ void resetAppWidget(AppWidgetProviderInfo info) {
+ mInfo = info;
+ mViewMode = VIEW_MODE_NOINIT;
+ updateAppWidget(null);
+ }
+
+ /**
* Process a set of {@link RemoteViews} coming in as an update from the
* AppWidget provider. Will animate into these new views as needed
*/
public void updateAppWidget(RemoteViews remoteViews) {
- updateAppWidget(remoteViews, 0);
- }
+ if (LOGD) Log.d(TAG, "updateAppWidget called mOld=" + mOld);
- void updateAppWidget(RemoteViews remoteViews, int flags) {
- if (LOGD) Log.d(TAG, "updateAppWidget called mOld=" + mOld + " flags=0x"
- + Integer.toHexString(flags));
-
- if ((flags & UPDATE_FLAGS_RESET) != 0) {
- mViewMode = VIEW_MODE_NOINIT;
- }
-
boolean recycled = false;
View content = null;
Exception exception = null;
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index b4718ab..69f7611 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -18,6 +18,7 @@
import android.accounts.Account;
import android.app.ActivityThread;
+import android.app.AppGlobals;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
@@ -1306,7 +1307,7 @@
// ActivityThread.currentPackageName() only returns non-null if the
// current thread is an application main thread. This parameter tells
// us whether an event loop is blocked, and if so, which app it is.
- String blockingPackage = ActivityThread.currentPackageName();
+ String blockingPackage = AppGlobals.getInitialPackage();
EventLog.writeEvent(
EventLogTags.CONTENT_QUERY_SAMPLE,
@@ -1329,7 +1330,7 @@
}
}
}
- String blockingPackage = ActivityThread.currentPackageName();
+ String blockingPackage = AppGlobals.getInitialPackage();
EventLog.writeEvent(
EventLogTags.CONTENT_UPDATE_SAMPLE,
uri.toString(),
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 0e798dc..cdc9bbb 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -19,6 +19,7 @@
import com.google.android.collect.Maps;
import android.app.ActivityThread;
+import android.app.AppGlobals;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.DatabaseUtils;
@@ -1921,7 +1922,7 @@
// main thread, or when we are invoked via Binder (e.g. ContentProvider).
// Hopefully the full path to the database will be informative enough.
- String blockingPackage = ActivityThread.currentPackageName();
+ String blockingPackage = AppGlobals.getInitialPackage();
if (blockingPackage == null) blockingPackage = "";
EventLog.writeEvent(
diff --git a/core/java/android/hardware/Usb.java b/core/java/android/hardware/Usb.java
new file mode 100644
index 0000000..e9c2cf7
--- /dev/null
+++ b/core/java/android/hardware/Usb.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.hardware;
+
+/**
+ * Class for accessing USB state information.
+ * @hide
+ */
+public class Usb {
+ /**
+ * Broadcast Action: A broadcast for USB connected events.
+ *
+ * The extras bundle will name/value pairs with the name of the function
+ * and a value of either {@link #USB_FUNCTION_ENABLED} or {@link #USB_FUNCTION_DISABLED}.
+ * Possible USB function names include {@link #USB_FUNCTION_MASS_STORAGE},
+ * {@link #USB_FUNCTION_ADB}, {@link #USB_FUNCTION_RNDIS} and {@link #USB_FUNCTION_MTP}.
+ */
+ public static final String ACTION_USB_CONNECTED =
+ "android.hardware.action.USB_CONNECTED";
+
+ /**
+ * Broadcast Action: A broadcast for USB disconnected events.
+ */
+ public static final String ACTION_USB_DISCONNECTED =
+ "android.hardware.action.USB_DISCONNECTED";
+
+
+ /**
+ * Name of the USB mass storage USB function.
+ * Used in extras for the {@link #ACTION_USB_CONNECTED} broadcast
+ */
+ public static final String USB_FUNCTION_MASS_STORAGE = "mass_storage";
+
+ /**
+ * Name of the adb USB function.
+ * Used in extras for the {@link #ACTION_USB_CONNECTED} broadcast
+ */
+ public static final String USB_FUNCTION_ADB = "adb";
+
+ /**
+ * Name of the RNDIS ethernet USB function.
+ * Used in extras for the {@link #ACTION_USB_CONNECTED} broadcast
+ */
+ public static final String USB_FUNCTION_RNDIS = "rndis";
+
+ /**
+ * Name of the MTP USB function.
+ * Used in extras for the {@link #ACTION_USB_CONNECTED} broadcast
+ */
+ public static final String USB_FUNCTION_MTP = "mtp";
+
+ /**
+ * Value indicating that a USB function is enabled.
+ * Used in extras for the {@link #ACTION_USB_CONNECTED} broadcast
+ */
+ public static final String USB_FUNCTION_ENABLED = "enabled";
+
+ /**
+ * Value indicating that a USB function is disabled.
+ * Used in extras for the {@link #ACTION_USB_CONNECTED} broadcast
+ */
+ public static final String USB_FUNCTION_DISABLED = "disabled";
+}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 045c24f..852630d 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -37,6 +37,7 @@
out List<IBinder> notificationKeys, out List<StatusBarNotification> notifications);
void onPanelRevealed();
void onNotificationClick(String pkg, String tag, int id);
- void onNotificationError(String pkg, String tag, int id, String message);
+ void onNotificationError(String pkg, String tag, int id,
+ int uid, int initialPid, String message);
void onClearAllNotifications();
}
diff --git a/core/java/com/android/internal/statusbar/StatusBarNotification.java b/core/java/com/android/internal/statusbar/StatusBarNotification.java
index 5499676..aa340fb 100644
--- a/core/java/com/android/internal/statusbar/StatusBarNotification.java
+++ b/core/java/com/android/internal/statusbar/StatusBarNotification.java
@@ -38,18 +38,23 @@
public String pkg;
public int id;
public String tag;
+ public int uid;
+ public int initialPid;
public Notification notification;
public StatusBarNotification() {
}
- public StatusBarNotification(String pkg, int id, String tag, Notification notification) {
+ public StatusBarNotification(String pkg, int id, String tag,
+ int uid, int initialPid, Notification notification) {
if (pkg == null) throw new NullPointerException();
if (notification == null) throw new NullPointerException();
this.pkg = pkg;
this.id = id;
this.tag = tag;
+ this.uid = uid;
+ this.initialPid = initialPid;
this.notification = notification;
}
@@ -65,6 +70,8 @@
} else {
this.tag = null;
}
+ this.uid = in.readInt();
+ this.initialPid = in.readInt();
this.notification = new Notification(in);
}
@@ -77,6 +84,8 @@
} else {
out.writeInt(0);
}
+ out.writeInt(this.uid);
+ out.writeInt(this.initialPid);
this.notification.writeToParcel(out, flags);
}
@@ -99,7 +108,8 @@
};
public StatusBarNotification clone() {
- return new StatusBarNotification(this.pkg, this.id, this.tag, this.notification.clone());
+ return new StatusBarNotification(this.pkg, this.id, this.tag,
+ this.uid, this.initialPid, this.notification.clone());
}
public String toString() {
diff --git a/core/jni/android_bluetooth_HeadsetBase.cpp b/core/jni/android_bluetooth_HeadsetBase.cpp
index 5593a26..4e9fbaf 100644
--- a/core/jni/android_bluetooth_HeadsetBase.cpp
+++ b/core/jni/android_bluetooth_HeadsetBase.cpp
@@ -169,7 +169,7 @@
// never receive non-ASCII UTF-8).
// This was added because of the BMW 2005 E46 which sends binary junk.
if (is_ascii(buf)) {
- LOG(LOG_INFO, "Bluetooth AT recv", "%s", buf);
+ IF_LOGV() LOG(LOG_VERBOSE, "Bluetooth AT recv", "%s", buf);
} else {
LOGW("Ignoring invalid AT command: %s", buf);
buf[0] = NULL;
@@ -494,7 +494,7 @@
}
}
}
- LOG(LOG_INFO, "Bluetooth AT sent", "%s", buf);
+ IF_LOGV() LOG(LOG_VERBOSE, "Bluetooth AT sent", "%s", buf);
free(buf);
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index aff9453..b1f81df 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -80,6 +80,9 @@
<protected-broadcast android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
<protected-broadcast android:name="android.bluetooth.device.action.PAIRING_CANCEL" />
+ <protected-broadcast android:name="android.hardware.action.USB_CONNECTED" />
+ <protected-broadcast android:name="android.hardware.action.USB_DISCONNECTED" />
+
<!-- ====================================== -->
<!-- Permissions for things that cost money -->
<!-- ====================================== -->
@@ -436,6 +439,14 @@
android:label="@string/permlab_flashlight"
android:description="@string/permdesc_flashlight" />
+ <!-- Allows an application to access USB devices
+ @hide -->
+ <permission android:name="android.permission.ACCESS_USB"
+ android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
+ android:protectionLevel="signatureOrSystem"
+ android:label="@string/permlab_accessUsb"
+ android:description="@string/permdesc_accessUsb" />
+
<!-- Allows access to hardware peripherals. Intended only for hardware testing -->
<permission android:name="android.permission.HARDWARE_TEST"
android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3c1fdbc..44317bc 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -939,6 +939,11 @@
the flashlight.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_accessUsb">access USB devices</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_accessUsb">Allows the application to access USB devices.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_hardware_test">test hardware</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_hardware_test">Allows the application to control
diff --git a/docs/html/license.jd b/docs/html/license.jd
index 88932b6..83cd470 100644
--- a/docs/html/license.jd
+++ b/docs/html/license.jd
@@ -74,7 +74,7 @@
<li>The use of sample source code provided in the SDK or shown in this
documentation is subject to the conditions detailed in the <a
-href="{@docRoot}sdk/terms.html">SDK Terms and Conditions</a>.</li>
+href="http://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 license</a>.</li>
</ul>
</h3>
diff --git a/docs/html/sdk/download.jd b/docs/html/sdk/download.jd
deleted file mode 100644
index 029de21..0000000
--- a/docs/html/sdk/download.jd
+++ /dev/null
@@ -1,80 +0,0 @@
-page.title=Download the Android SDK
-hide_license_footer=true
-
-@jd:body
-
-<script type="text/javascript">
- function verify() {
- document.getElementById('download-button').disabled = !document.getElementById('checkbox').checked;
- }
- function submit() {
- var location = window.location.href;
- if (location.indexOf('?v=') != -1) {
- var filename = location.substring(location.indexOf('=')+1,location.length);
- if (document.getElementById('checkbox').checked) {
- document.location = "http://dl.google.com/android/" + filename;
- }
- document.getElementById('click-download').setAttribute("href", "http://dl.google.com/android/" + filename);
- $("#terms-form").hide(500);
- $("#next-steps").show(500);
- document.getElementById('checkbox').disabled=true;
- document.getElementById('download-button').disabled=true;
- } else {
- alert("You have not selected an SDK version. Please return to the Download page");
- }
- }
-</script>
-
-<div id="terms-form">
- <p>Please carefully review the Android SDK License Agreement before downloading the SDK.
-The License Agreement constitutes a contract between you and Google with respect to your use of the SDK.</p>
-
- <iframe id="terms" style="border:1px solid #888;margin:0 0 1em;height:400px;width:95%;" src="terms_body.html">
- </iframe>
-
- <p>
- <input type="checkbox" id="checkbox" onclick="verify()" />
- <label for="checkbox">I agree to the terms of the Android SDK License Agreement.</label>
- </p>
- <p>
- <input type="submit" value="Download" id="download-button" disabled="disabled" onclick="submit()" />
- </p>
- <p>
- <script language="javascript">
- var loc = window.location.href;
- if (loc.indexOf('?v=') != -1) {
- var filename = loc.substring(loc.indexOf('=')+1,loc.length);
- document.write("File: " + filename);
- }
- </script>
- </p>
-</div><!-- end terms-form -->
-
-<noscript>
- <p><strong>Please enable Javascript in your browser in order to agree to the terms and download the SDK.</strong></p>
-</noscript>
-
-<div class="special" id="next-steps" style="display:none">
- <h2>Thank you for downloading the Android SDK!</h2>
- <p>Your download should be underway. If not, <a id="click-download">click here to start the download</a>.</p>
- <p>To set up your Android development environment, please read the guide to
- <a href="installing.html">Installing the Android SDK</a> and ensure that your development
- machine meets the system requirements linked on that page.</p>
-</div>
-
-<script type="text/javascript">
- var loc = window.location.href;
- var filename = loc.substring(loc.indexOf('=')+1,loc.length);
- version = filename.substring(filename.indexOf('.')-1,filename.lastIndexOf('.'));
- $(".addVersionPath").each(function(i) {
- var oldHref = $(this).attr("href");
- $(this).attr({href: "/sdk/" + version + "/" + oldHref});
- });
-</script>
-
-
-
-
-
-
-
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 7438707..a80981ce 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -133,7 +133,6 @@
</h2>
<ul>
<li><a href="<?cs var:toroot ?>sdk/requirements.html">SDK System Requirements</a></li>
- <li><a href="<?cs var:toroot ?>sdk/terms.html">SDK Terms and Conditions</a></li>
<!-- <li><a href="<?cs var:toroot ?>sdk/RELEASENOTES.html">SDK Release
Notes</a></li> -->
<li><a href="<?cs var:toroot ?>sdk/older_releases.html">SDK
diff --git a/docs/html/sdk/terms_body.html b/docs/html/sdk/terms_body.html
deleted file mode 100644
index 03e0906..0000000
--- a/docs/html/sdk/terms_body.html
+++ /dev/null
@@ -1,204 +0,0 @@
-
-<p>This is the Android Software Development Kit License Agreement.</p>
-
-<h2>
- 1. Introduction
-</h2>
-<p>
- 1.1 The Android Software Development Kit (referred to in this License Agreement as the "SDK" and specifically including the Android system files, packaged APIs, and Google APIs add-ons) is licensed to you subject to the terms of this License Agreement. This License Agreement forms a legally binding contract between you and Google in relation to your use of the SDK.
-
-</p>
-<p>
- 1.2 "Google" means Google Inc., a Delaware corporation with principal place of business at 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States.
-</p>
-<h2>
- 2. Accepting this License Agreement
-</h2>
-<p>
- 2.1 In order to use the SDK, you must first agree to this License Agreement. You may not use the SDK if you do not accept this License Agreement.
-</p>
-<p>
- 2.2 You can accept this License Agreement by:
-</p>
-<p>
- (A) clicking to accept or agree to this License Agreement, where this option is made available to you; or
-</p>
-<p>
- (B) by actually using the SDK. In this case, you agree that use of the SDK constitutes acceptance of the Licensing Agreement from that point onwards.
-</p>
-<p>
- 2.3 You may not use the SDK and may not accept the Licensing Agreement if you are a person barred from receiving the SDK under the laws of the United States or other countries including the country in which you are resident or from which you use the SDK.
-</p>
-<p>
- 2.4 If you are agreeing to be bound by this License Agreement on behalf of your employer or other entity, you represent and warrant that you have full legal authority to bind your employer or such entity to this License Agreement. If you do not have the requisite authority, you may not accept the Licensing Agreement or use the SDK on behalf of your employer or other entity.
-</p>
-<h2>
- 3. SDK License from Google
-</h2>
-<p>
- 3.1 Subject to the terms of this License Agreement, Google grants you a limited, worldwide, royalty-free, non- assignable and non-exclusive license to use the SDK solely to develop applications to run on the Android platform.
-</p>
-<p>
- 3.2 You agree that Google or third parties own all legal right, title and interest in and to the SDK, including any Intellectual Property Rights that subsist in the SDK. "Intellectual Property Rights" means any and all rights under patent law, copyright law, trade secret law, trademark law, and any and all other proprietary rights. Google reserves all rights not expressly granted to you.
-
-</p>
-<p>
- 3.3 Except to the extent required by applicable third party licenses, you may not copy (except for backup purposes), modify, adapt, redistribute, decompile, reverse engineer, disassemble, or create derivative works of the SDK or any part of the SDK. Except to the extent required by applicable third party licenses, you may not load any part of the SDK onto a mobile handset or any other hardware device except a personal computer, combine any part of the SDK with other software, or distribute any software or device incorporating a part of the SDK.
-</p>
-<p>
- 3.4 Use, reproduction and distribution of components of the SDK licensed under an open source software license are governed solely by the terms of that open source software license and not this License Agreement.
-</p>
-<p>
- 3.5 You agree that the form and nature of the SDK that Google provides may change without prior notice to you and that future versions of the SDK may be incompatible with applications developed on previous versions of the SDK. You agree that Google may stop (permanently or temporarily) providing the SDK (or any features within the SDK) to you or to users generally at Google's sole discretion, without prior notice to you.
-</p>
-<p>
- 3.6 Nothing in this License Agreement gives you a right to use any of Google's trade names, trademarks, service marks, logos, domain names, or other distinctive brand features.
-</p>
-<p>
- 3.7 You agree that you will not remove, obscure, or alter any proprietary rights notices (including copyright and trademark notices) that may be affixed to or contained within the SDK.
-</p>
-<h2>
- 4. Use of the SDK by You
-</h2>
-<p>
- 4.1 Google agrees that it obtains no right, title or interest from you (or your licensors) under this License Agreement in or to any software applications that you develop using the SDK, including any intellectual property rights that subsist in those applications.
-</p>
-<p>
- 4.2 You agree to use the SDK and write applications only for purposes that are permitted by (a) this License Agreement and (b) any applicable law, regulation or generally accepted practices or guidelines in the relevant jurisdictions (including any laws regarding the export of data or software to and from the United States or other relevant countries).
-</p>
-<p>
- 4.3 You agree that if you use the SDK to develop applications for general public users, you will protect the privacy and legal rights of those users. If the users provide you with user names, passwords, or other login information or personal information, your must make the users aware that the information will be available to your application, and you must provide legally adequate privacy notice and protection for those users. If your application stores personal or sensitive information provided by users, it must do so securely. If the user provides your application with Google Account information, your application may only use that information to access the user's Google Account when, and for the limited purposes for which, the user has given you permission to do so.
-</p>
-<p>
- 4.4 You agree that you will not engage in any activity with the SDK, including the development or distribution of an application, that interferes with, disrupts, damages, or accesses in an unauthorized manner the servers, networks, or other properties or services of any third party including, but not limited to, Google or any mobile communications carrier.
-</p>
-<p>
- 4.5 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any data, content, or resources that you create, transmit or display through the Android platform and/or applications for the Android platform, and for the consequences of your actions (including any loss or damage which Google may suffer) by doing so.
-</p>
-<p>
- 4.6 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any breach of your obligations under this License Agreement, any applicable third party contract or Terms of Service, or any applicable law or regulation, and for the consequences (including any loss or damage which Google or any third party may suffer) of any such breach.
-</p>
-<h2>
- 5. Your Developer Credentials
-</h2>
-<p>
- 5.1 You agree that you are responsible for maintaining the confidentiality of any developer credentials that may be issued to you by Google or which you may choose yourself and that you will be solely responsible for all applications that are developed under your developer credentials.
-</p>
-<h2>
- 6. Privacy and Information
-</h2>
-<p>
- 6.1 In order to continually innovate and improve the SDK, Google may collect certain usage statistics from the software including but not limited to a unique identifier, associated IP address, version number of the software, and information on which tools and/or services in the SDK are being used and how they are being used. Before any of this information is collected, the SDK will notify you and seek your consent. If you withhold consent, the information will not be collected.
-</p>
-<p>
- 6.2 The data collected is examined in the aggregate to improve the SDK and is maintained in accordance with Google's Privacy Policy.
-</p>
-<h2>
- 7. Third Party Applications for the Android Platform
-</h2>
-<p>
- 7.1 If you use the SDK to run applications developed by a third party or that access data, content or resources provided by a third party, you agree that Google is not responsible for those applications, data, content, or resources. You understand that all data, content or resources which you may access through such third party applications are the sole responsibility of the person from which they originated and that Google is not liable for any loss or damage that you may experience as a result of the use or access of any of those third party applications, data, content, or resources.
-</p>
-<p>
- 7.2 You should be aware the data, content, and resources presented to you through such a third party application may be protected by intellectual property rights which are owned by the providers (or by other persons or companies on their behalf). You may not modify, rent, lease, loan, sell, distribute or create derivative works based on these data, content, or resources (either in whole or in part) unless you have been specifically given permission to do so by the relevant owners.
-</p>
-<p>
- 7.3 You acknowledge that your use of such third party applications, data, content, or resources may be subject to separate terms between you and the relevant third party. In that case, this License Agreement does not affect your legal relationship with these third parties.
-</p>
-<h2>
- 8. Using Android APIs
-</h2>
-<p>
- 8.1 Google Data APIs
-</p>
-<p>
- 8.1.1 If you use any API to retrieve data from Google, you acknowledge that the data may be protected by intellectual property rights which are owned by Google or those parties that provide the data (or by other persons or companies on their behalf). Your use of any such API may be subject to additional Terms of Service. You may not modify, rent, lease, loan, sell, distribute or create derivative works based on this data (either in whole or in part) unless allowed by the relevant Terms of Service.
-</p>
-<p>
- 8.1.2 If you use any API to retrieve a user's data from Google, you acknowledge and agree that you shall retrieve data only with the user's explicit consent and only when, and for the limited purposes for which, the user has given you permission to do so.
-
-</p>
-<h2>
- 9. Terminating this License Agreement
-</h2>
-<p>
- 9.1 This License Agreement will continue to apply until terminated by either you or Google as set out below.
-</p>
-<p>
- 9.2 If you want to terminate this License Agreement, you may do so by ceasing your use of the SDK and any relevant developer credentials.
-</p>
-<p>
- 9.3 Google may at any time, terminate this License Agreement with you if:
-</p>
-<p>
- (A) you have breached any provision of this License Agreement; or
-</p>
-<p>
- (B) Google is required to do so by law; or
-</p>
-<p>
- (C) the partner with whom Google offered certain parts of SDK (such as APIs) to you has terminated its relationship with Google or ceased to offer certain parts of the SDK to you; or
-</p>
-<p>
- (D) Google decides to no longer providing the SDK or certain parts of the SDK to users in the country in which you are resident or from which you use the service, or the provision of the SDK or certain SDK services to you by Google is, in Google's sole discretion, no longer commercially viable.
-</p>
-<p>
- 9.4 When this License Agreement comes to an end, all of the legal rights, obligations and liabilities that you and Google have benefited from, been subject to (or which have accrued over time whilst this License Agreement has been in force) or which are expressed to continue indefinitely, shall be unaffected by this cessation, and the provisions of paragraph 14.7 shall continue to apply to such rights, obligations and liabilities indefinitely.
-</p>
-<h2>
- 10. DISCLAIMER OF WARRANTIES
-</h2>
-<p>
- 10.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE RISK AND THAT THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF ANY KIND FROM GOOGLE.
-</p>
-<p>
- 10.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF DATA THAT RESULTS FROM SUCH USE.
-</p>
-<p>
- 10.3 GOOGLE FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
-</p>
-<h2>
- 11. LIMITATION OF LIABILITY
-</h2>
-<p>
- 11.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL CONSEQUENTIAL OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS OF DATA, WHETHER OR NOT GOOGLE OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING.
-</p>
-<h2>
- 12. Indemnification
-</h2>
-<p>
- 12.1 To the maximum extent permitted by law, you agree to defend, indemnify and hold harmless Google, its affiliates and their respective directors, officers, employees and agents from and against any and all claims, actions, suits or proceedings, as well as any and all losses, liabilities, damages, costs and expenses (including reasonable attorneys fees) arising out of or accruing from (a) your use of the SDK, (b) any application you develop on the SDK that infringes any copyright, trademark, trade secret, trade dress, patent or other intellectual property right of any person or defames any person or violates their rights of publicity or privacy, and (c) any non-compliance by you with this License Agreement.
-</p>
-<h2>
- 13. Changes to the License Agreement
-</h2>
-<p>
- 13.1 Google may make changes to the License Agreement as it distributes new versions of the SDK. When these changes are made, Google will make a new version of the License Agreement available on the website where the SDK is made available.
-</p>
-<h2>
- 14. General Legal Terms
-</h2>
-<p>
- 14.1 This License Agreement constitute the whole legal agreement between you and Google and govern your use of the SDK (excluding any services which Google may provide to you under a separate written agreement), and completely replace any prior agreements between you and Google in relation to the SDK.
-</p>
-<p>
- 14.2 You agree that if Google does not exercise or enforce any legal right or remedy which is contained in this License Agreement (or which Google has the benefit of under any applicable law), this will not be taken to be a formal waiver of Google's rights and that those rights or remedies will still be available to Google.
-</p>
-<p>
- 14.3 If any court of law, having the jurisdiction to decide on this matter, rules that any provision of this License Agreement is invalid, then that provision will be removed from this License Agreement without affecting the rest of this License Agreement. The remaining provisions of this License Agreement will continue to be valid and enforceable.
-</p>
-<p>
- 14.4 You acknowledge and agree that each member of the group of companies of which Google is the parent shall be third party beneficiaries to this License Agreement and that such other companies shall be entitled to directly enforce, and rely upon, any provision of this License Agreement that confers a benefit on (or rights in favor of) them. Other than this, no other person or company shall be third party beneficiaries to this License Agreement.
-</p>
-<p>
- 14.5 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND REGULATIONS THAT APPLY TO THE SDK. THESE LAWS INCLUDE RESTRICTIONS ON DESTINATIONS, END USERS AND END USE.
-</p>
-<p>
- 14.6 The rights granted in this License Agreement may not be assigned or transferred by either you or Google without the prior written approval of the other party. Neither you nor Google shall be permitted to delegate their responsibilities or obligations under this License Agreement without the prior written approval of the other party.
-</p>
-<p>
- 14.7 This License Agreement, and your relationship with Google under this License Agreement, shall be governed by the laws of the State of California without regard to its conflict of laws provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located within the county of Santa Clara, California to resolve any legal matter arising from this License Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction.
-</p>
-<p>
- <em>April 10, 2009</em>
-</p>
diff --git a/docs/html/sitemap.txt b/docs/html/sitemap.txt
index b0ec7c9..d5be8f1 100644
--- a/docs/html/sitemap.txt
+++ b/docs/html/sitemap.txt
@@ -7,7 +7,6 @@
http://developer.android.com/videos/index.html
http://developer.android.com/resources/dashboard/platform-versions.html
http://developer.android.com/license.html
-http://developer.android.com/sdk/terms.html
http://developer.android.com/resources/community-groups.html
http://developer.android.com/resources/community-more.html
http://developer.android.com/resources/articles/index.html
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 9e606d9..3662983 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -39,7 +39,6 @@
enum player_type {
PV_PLAYER = 1,
SONIVOX_PLAYER = 2,
- VORBIS_PLAYER = 3,
STAGEFRIGHT_PLAYER = 4,
// Test players are available only in the 'test' and 'eng' builds.
// The shared library with the test player is passed passed as an
diff --git a/include/media/stagefright/AMRWriter.h b/include/media/stagefright/AMRWriter.h
index b0eaba4..813dd43 100644
--- a/include/media/stagefright/AMRWriter.h
+++ b/include/media/stagefright/AMRWriter.h
@@ -26,6 +26,7 @@
namespace android {
struct MediaSource;
+struct MetaData;
struct AMRWriter : public MediaWriter {
AMRWriter(const char *filename);
@@ -35,7 +36,7 @@
virtual status_t addSource(const sp<MediaSource> &source);
virtual bool reachedEOS();
- virtual status_t start();
+ virtual status_t start(MetaData *params = NULL);
virtual void stop();
virtual void pause();
diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h
index f2001e1..628200d 100644
--- a/include/media/stagefright/AudioSource.h
+++ b/include/media/stagefright/AudioSource.h
@@ -39,6 +39,9 @@
virtual status_t stop();
virtual sp<MetaData> getFormat();
+ // Returns the maximum amplitude since last call.
+ int16_t getMaxAmplitude();
+
virtual status_t read(
MediaBuffer **buffer, const ReadOptions *options = NULL);
@@ -53,13 +56,17 @@
bool mStarted;
bool mCollectStats;
+ bool mTrackMaxAmplitude;
int64_t mTotalReadTimeUs;
int64_t mTotalReadBytes;
int64_t mTotalReads;
int64_t mStartTimeUs;
+ int16_t mMaxAmplitude;
MediaBufferGroup *mGroup;
+ void trackMaxAmplitude(int16_t *data, int nSamples);
+
AudioSource(const AudioSource &);
AudioSource &operator=(const AudioSource &);
};
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 39d0ea1..7a2de1e 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -36,7 +36,7 @@
MPEG4Writer(int fd);
virtual status_t addSource(const sp<MediaSource> &source);
- virtual status_t start();
+ virtual status_t start(MetaData *param = NULL);
virtual bool reachedEOS();
virtual void stop();
virtual void pause();
@@ -83,6 +83,7 @@
int64_t getStartTimestampUs(); // Not const
status_t startTracks();
size_t numTracks();
+ int64_t estimateMoovBoxSize(int32_t bitRate);
void lock();
void unlock();
diff --git a/include/media/stagefright/MediaWriter.h b/include/media/stagefright/MediaWriter.h
index 8528203..46aaf7c 100644
--- a/include/media/stagefright/MediaWriter.h
+++ b/include/media/stagefright/MediaWriter.h
@@ -24,13 +24,14 @@
namespace android {
struct MediaSource;
+struct MetaData;
struct MediaWriter : public RefBase {
MediaWriter() {}
virtual status_t addSource(const sp<MediaSource> &source) = 0;
virtual bool reachedEOS() = 0;
- virtual status_t start() = 0;
+ virtual status_t start(MetaData *params = NULL) = 0;
virtual void stop() = 0;
virtual void pause() = 0;
virtual void setMaxFileSize(int64_t bytes) { mMaxFileSizeLimitBytes = bytes; }
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 6a20602..d28d1ca 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -36,13 +36,14 @@
kKeyStride = 'strd', // int32_t
kKeySliceHeight = 'slht', // int32_t
kKeyChannelCount = '#chn', // int32_t
- kKeySampleRate = 'srte', // int32_t
+ kKeySampleRate = 'srte', // int32_t (also video frame rate)
kKeyBitRate = 'brte', // int32_t (bps)
kKeyESDS = 'esds', // raw data
kKeyAVCC = 'avcc', // raw data
kKeyVorbisInfo = 'vinf', // raw data
kKeyVorbisBooks = 'vboo', // raw data
kKeyWantsNALFragments = 'NALf',
+ kKey64BitFileOffset = 'fobt', // int32_t (bool)
kKeyIsSyncFrame = 'sync', // int32_t (bool)
kKeyIsCodecConfig = 'conf', // int32_t (bool)
kKeyTime = 'time', // int64_t (usecs)
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 198e865..6eec215a 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -24,6 +24,7 @@
libui \
libcutils \
libsurfaceflinger_client \
+ libstagefright \
libcamera_client
ifneq ($(BUILD_WITHOUT_PV),true)
@@ -34,15 +35,6 @@
LOCAL_CFLAGS += -DNO_OPENCORE
endif
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
-LOCAL_CFLAGS += -DBUILD_WITH_FULL_STAGEFRIGHT=1
-
-LOCAL_SHARED_LIBRARIES += \
- libstagefright
-
-endif
-
LOCAL_STATIC_LIBRARIES :=
LOCAL_C_INCLUDES += \
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
index 2ab2445..273f1af 100644
--- a/media/jni/android_media_MediaScanner.cpp
+++ b/media/jni/android_media_MediaScanner.cpp
@@ -31,13 +31,7 @@
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
-#ifndef NO_OPENCORE
-#include "pvmediascanner.h"
-#endif
-
-#if BUILD_WITH_FULL_STAGEFRIGHT
#include <media/stagefright/StagefrightMediaScanner.h>
-#endif
// ----------------------------------------------------------------------------
@@ -286,25 +280,10 @@
}
}
-static MediaScanner *createMediaScanner() {
-#if BUILD_WITH_FULL_STAGEFRIGHT
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.enable-scan", value, NULL)
- && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
- return new StagefrightMediaScanner;
- }
-#endif
-#ifndef NO_OPENCORE
- return new PVMediaScanner();
-#endif
-
- return NULL;
-}
-
static void
android_media_MediaScanner_native_setup(JNIEnv *env, jobject thiz)
{
- MediaScanner *mp = createMediaScanner();
+ MediaScanner *mp = new StagefrightMediaScanner;
if (mp == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index 3b678cb..8f010c9 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -11,21 +11,11 @@
MediaPlayerService.cpp \
MetadataRetrieverClient.cpp \
TestPlayerStub.cpp \
- VorbisPlayer.cpp \
- VorbisMetadataRetriever.cpp \
- MidiMetadataRetriever.cpp \
- MidiFile.cpp
-
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
-LOCAL_SRC_FILES += \
- StagefrightPlayer.cpp \
+ MidiMetadataRetriever.cpp \
+ MidiFile.cpp \
+ StagefrightPlayer.cpp \
StagefrightRecorder.cpp
-LOCAL_CFLAGS += -DBUILD_WITH_FULL_STAGEFRIGHT=1
-
-endif
-
ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
LOCAL_LDLIBS += -ldl -lpthread
endif
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index d45c17b..82d5c14 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -56,7 +56,6 @@
#include "MetadataRetrieverClient.h"
#include "MidiFile.h"
-#include "VorbisPlayer.h"
#include <media/PVPlayer.h>
#include "TestPlayerStub.h"
#include "StagefrightPlayer.h"
@@ -197,8 +196,6 @@
{".rtttl", SONIVOX_PLAYER},
{".rtx", SONIVOX_PLAYER},
{".ota", SONIVOX_PLAYER},
- {".ogg", VORBIS_PLAYER},
- {".oga", VORBIS_PLAYER},
#ifndef NO_OPENCORE
{".wma", PV_PLAYER},
{".wmv", PV_PLAYER},
@@ -666,37 +663,9 @@
}
static player_type getDefaultPlayerType() {
-#if BUILD_WITH_FULL_STAGEFRIGHT
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.enable-player", value, NULL)
- && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
- return STAGEFRIGHT_PLAYER;
- }
-#endif
-
- return PV_PLAYER;
+ return STAGEFRIGHT_PLAYER;
}
-// By default we use the VORBIS_PLAYER for vorbis playback (duh!),
-// but if the magic property is set we will use our new experimental
-// stagefright code instead.
-static player_type OverrideStagefrightForVorbis(player_type player) {
- if (player != VORBIS_PLAYER) {
- return player;
- }
-
-#if BUILD_WITH_FULL_STAGEFRIGHT
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.enable-vorbis", value, NULL)
- && (!strcmp(value, "1") || !strcmp(value, "true"))) {
- return STAGEFRIGHT_PLAYER;
- }
-#endif
-
- return VORBIS_PLAYER;
-}
-
-
player_type getPlayerType(int fd, int64_t offset, int64_t length)
{
char buf[20];
@@ -708,7 +677,7 @@
// Ogg vorbis?
if (ident == 0x5367674f) // 'OggS'
- return OverrideStagefrightForVorbis(VORBIS_PLAYER);
+ return STAGEFRIGHT_PLAYER;
#ifndef NO_OPENCORE
if (ident == 0x75b22630) {
@@ -744,13 +713,6 @@
return TEST_PLAYER;
}
- bool useStagefrightForHTTP = false;
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.enable-http", value, NULL)
- && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
- useStagefrightForHTTP = true;
- }
-
// use MidiFile for MIDI extensions
int lenURL = strlen(url);
for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
@@ -758,22 +720,11 @@
int start = lenURL - len;
if (start > 0) {
if (!strncasecmp(url + start, FILE_EXTS[i].extension, len)) {
- if (FILE_EXTS[i].playertype == VORBIS_PLAYER
- && !strncasecmp(url, "http://", 7)
- && useStagefrightForHTTP) {
- return STAGEFRIGHT_PLAYER;
- }
- return OverrideStagefrightForVorbis(FILE_EXTS[i].playertype);
+ return FILE_EXTS[i].playertype;
}
}
}
- if (!strncasecmp(url, "http://", 7)) {
- if (!useStagefrightForHTTP) {
- return PV_PLAYER;
- }
- }
-
if (!strncasecmp(url, "rtsp://", 7)) {
char value[PROPERTY_VALUE_MAX];
if (!property_get("media.stagefright.enable-rtsp", value, NULL)
@@ -802,16 +753,10 @@
LOGV(" create MidiFile");
p = new MidiFile();
break;
- case VORBIS_PLAYER:
- LOGV(" create VorbisPlayer");
- p = new VorbisPlayer();
- break;
-#if BUILD_WITH_FULL_STAGEFRIGHT
case STAGEFRIGHT_PLAYER:
LOGV(" create StagefrightPlayer");
p = new StagefrightPlayer;
break;
-#endif
case TEST_PLAYER:
LOGV("Create Test Player stub");
p = new TestPlayerStub();
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index c507669..084f039 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -294,13 +294,11 @@
LOGV("Client constructor");
mPid = pid;
-#if BUILD_WITH_FULL_STAGEFRIGHT
char value[PROPERTY_VALUE_MAX];
if (property_get("media.stagefright.enable-record", value, NULL)
&& (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
mRecorder = new StagefrightRecorder;
} else
-#endif
#ifndef NO_OPENCORE
{
mRecorder = new PVMediaRecorder();
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 550b84df..ca229fa 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -37,7 +37,6 @@
#include <media/MediaPlayerInterface.h>
#include <media/PVMetadataRetriever.h>
#include <private/media/VideoFrame.h>
-#include "VorbisMetadataRetriever.h"
#include "MidiMetadataRetriever.h"
#include "MetadataRetrieverClient.h"
#include "StagefrightMetadataRetriever.h"
@@ -103,30 +102,17 @@
{
sp<MediaMetadataRetrieverBase> p;
switch (playerType) {
-#if BUILD_WITH_FULL_STAGEFRIGHT
case STAGEFRIGHT_PLAYER:
{
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.enable-meta", value, NULL)
- && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
- LOGV("create StagefrightMetadataRetriever");
- p = new StagefrightMetadataRetriever;
- break;
- }
-
- // fall through
+ p = new StagefrightMetadataRetriever;
+ break;
}
-#endif
#ifndef NO_OPENCORE
case PV_PLAYER:
LOGV("create pv metadata retriever");
p = new PVMetadataRetriever();
break;
#endif
- case VORBIS_PLAYER:
- LOGV("create vorbis metadata retriever");
- p = new VorbisMetadataRetriever();
- break;
case SONIVOX_PLAYER:
LOGV("create midi metadata retriever");
p = new MidiMetadataRetriever();
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index d49c4e0..6834491 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -316,6 +316,13 @@
return OK;
}
+status_t StagefrightRecorder::setParam64BitFileOffset(bool use64Bit) {
+ LOGV("setParam64BitFileOffset: %s",
+ use64Bit? "use 64 bit file offset": "use 32 bit file offset");
+ mUse64BitFileOffset = use64Bit;
+ return OK;
+}
+
status_t StagefrightRecorder::setParameter(
const String8 &key, const String8 &value) {
LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
@@ -361,6 +368,11 @@
if (safe_strtoi32(value.string(), &interval)) {
return setParamIFramesInterval(interval);
}
+ } else if (key == "param-use-64bit-offset") {
+ int32_t use64BitOffset;
+ if (safe_strtoi32(value.string(), &use64BitOffset)) {
+ return setParam64BitFileOffset(use64BitOffset != 0);
+ }
} else {
LOGE("setParameter: failed to find key %s", key.string());
}
@@ -484,6 +496,7 @@
sp<MediaSource> audioEncoder =
OMXCodec::Create(client.interface(), encMeta,
true /* createEncoder */, audioSource);
+ mAudioSourceNode = audioSource;
return audioEncoder;
}
@@ -632,6 +645,7 @@
status_t StagefrightRecorder::startMPEG4Recording() {
mWriter = new MPEG4Writer(dup(mOutputFd));
+ int32_t totalBitRate = 0;
// Add audio source first if it exists
if (mAudioSource != AUDIO_SOURCE_LIST_END) {
@@ -650,7 +664,7 @@
if (audioEncoder == NULL) {
return UNKNOWN_ERROR;
}
-
+ totalBitRate += mAudioBitRate;
mWriter->addSource(audioEncoder);
}
if (mVideoSource == VIDEO_SOURCE_DEFAULT
@@ -703,7 +717,7 @@
sp<MetaData> enc_meta = new MetaData;
enc_meta->setInt32(kKeyBitRate, mVideoBitRate);
- enc_meta->setInt32(kKeySampleRate, mFrameRate); // XXX: kKeySampleRate?
+ enc_meta->setInt32(kKeySampleRate, mFrameRate);
switch (mVideoEncoder) {
case VIDEO_ENCODER_H263:
@@ -746,12 +760,13 @@
true /* createEncoder */, cameraSource);
CHECK(mOutputFd >= 0);
+ totalBitRate += mVideoBitRate;
mWriter->addSource(encoder);
}
{
// MPEGWriter specific handling
- MPEG4Writer *writer = ((MPEG4Writer *) mWriter.get()); // mWriter is an MPEGWriter
+ MPEG4Writer *writer = ((MPEG4Writer *) mWriter.get());
writer->setInterleaveDuration(mInterleaveDurationUs);
}
@@ -762,7 +777,10 @@
mWriter->setMaxFileSize(mMaxFileSizeBytes);
}
mWriter->setListener(mListener);
- mWriter->start();
+ sp<MetaData> meta = new MetaData;
+ meta->setInt32(kKeyBitRate, totalBitRate);
+ meta->setInt32(kKey64BitFileOffset, mUse64BitFileOffset);
+ mWriter->start(meta.get());
return OK;
}
@@ -822,6 +840,8 @@
mAudioBitRate = 12200;
mInterleaveDurationUs = 0;
mIFramesInterval = 1;
+ mAudioSourceNode = 0;
+ mUse64BitFileOffset = false;
mEncoderProfiles = MediaProfiles::getInstance();
mOutputFd = -1;
@@ -831,7 +851,11 @@
}
status_t StagefrightRecorder::getMaxAmplitude(int *max) {
- *max = 0;
+ if (mAudioSourceNode != 0) {
+ *max = mAudioSourceNode->getMaxAmplitude();
+ } else {
+ *max = 0;
+ }
return OK;
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 7de96f6..2943e97 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -26,6 +26,7 @@
class Camera;
struct MediaSource;
struct MediaWriter;
+struct AudioSource;
class MediaProfiles;
struct StagefrightRecorder : public MediaRecorderBase {
@@ -64,12 +65,14 @@
sp<ISurface> mPreviewSurface;
sp<IMediaPlayerClient> mListener;
sp<MediaWriter> mWriter;
+ sp<AudioSource> mAudioSourceNode;
audio_source mAudioSource;
video_source mVideoSource;
output_format mOutputFormat;
audio_encoder mAudioEncoder;
video_encoder mVideoEncoder;
+ bool mUse64BitFileOffset;
int32_t mVideoWidth, mVideoHeight;
int32_t mFrameRate;
int32_t mVideoBitRate;
@@ -98,6 +101,7 @@
status_t setParamAudioSamplingRate(int32_t sampleRate);
status_t setParamInterleaveDuration(int32_t durationUs);
status_t setParamIFramesInterval(int32_t interval);
+ status_t setParam64BitFileOffset(bool use64BitFileOffset);
status_t setParamMaxDurationOrFileSize(int64_t limit, bool limit_is_duration);
void clipVideoBitRate();
void clipVideoFrameRate();
diff --git a/media/libmediaplayerservice/VorbisMetadataRetriever.cpp b/media/libmediaplayerservice/VorbisMetadataRetriever.cpp
deleted file mode 100644
index eac74fc..0000000
--- a/media/libmediaplayerservice/VorbisMetadataRetriever.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "VorbisMetadataRetriever"
-#include <utils/Log.h>
-
-#include "VorbisMetadataRetriever.h"
-#include <media/mediametadataretriever.h>
-#
-
-namespace android {
-
-void VorbisMetadataRetriever::clearMetadataValues()
-{
- LOGV("cleearMetadataValues");
- mMetadataValues[0][0] = '\0';
-}
-
-status_t VorbisMetadataRetriever::setDataSource(const char *url)
-{
- LOGV("setDataSource: url(%s)", url? url: "NULL pointer");
- Mutex::Autolock lock(mLock);
- clearMetadataValues();
- if (mVorbisPlayer == 0) {
- mVorbisPlayer = new VorbisPlayer();
- }
- // TODO: support headers in MetadataRetriever interface!
- return mVorbisPlayer->setDataSource(url, NULL /* headers */);
-}
-
-status_t VorbisMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
-{
- LOGV("setDataSource: fd(%d), offset(%lld), and length(%lld)", fd, offset, length);
- Mutex::Autolock lock(mLock);
- clearMetadataValues();
- if (mVorbisPlayer == 0) {
- mVorbisPlayer = new VorbisPlayer();
- }
- return mVorbisPlayer->setDataSource(fd, offset, length);
-}
-
-const char* VorbisMetadataRetriever::extractMetadata(int keyCode)
-{
- LOGV("extractMetadata: key(%d)", keyCode);
- Mutex::Autolock lock(mLock);
- if (mVorbisPlayer == 0 || mVorbisPlayer->initCheck() != NO_ERROR) {
- LOGE("no vorbis player is initialized yet");
- return NULL;
- }
- switch (keyCode) {
- case METADATA_KEY_DURATION:
- {
- if (mMetadataValues[0][0] == '\0') {
- int duration = -1;
- if (mVorbisPlayer->getDuration(&duration) != NO_ERROR) {
- LOGE("failed to get duration");
- return NULL;
- }
- snprintf(mMetadataValues[0], MAX_METADATA_STRING_LENGTH, "%d", duration);
- }
- LOGV("duration: %s ms", mMetadataValues[0]);
- return mMetadataValues[0];
- }
- default:
- LOGE("Unsupported key code (%d)", keyCode);
- return NULL;
- }
- return NULL;
-}
-
-};
-
diff --git a/media/libmediaplayerservice/VorbisMetadataRetriever.h b/media/libmediaplayerservice/VorbisMetadataRetriever.h
deleted file mode 100644
index 1c57fe3..0000000
--- a/media/libmediaplayerservice/VorbisMetadataRetriever.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-**
-** Copyright 2009, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_VORBISMETADATARETRIEVER_H
-#define ANDROID_VORBISMETADATARETRIEVER_H
-
-#include <utils/threads.h>
-#include <utils/Errors.h>
-#include <media/MediaMetadataRetrieverInterface.h>
-
-#include "VorbisPlayer.h"
-
-namespace android {
-
-class VorbisMetadataRetriever : public MediaMetadataRetrieverInterface {
-public:
- VorbisMetadataRetriever() {}
- ~VorbisMetadataRetriever() {}
-
- virtual status_t setDataSource(const char *url);
- virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
- virtual const char* extractMetadata(int keyCode);
-
-private:
- static const uint32_t MAX_METADATA_STRING_LENGTH = 128;
- void clearMetadataValues();
-
- Mutex mLock;
- sp<VorbisPlayer> mVorbisPlayer;
- char mMetadataValues[1][MAX_METADATA_STRING_LENGTH];
-};
-
-}; // namespace android
-
-#endif // ANDROID_VORBISMETADATARETRIEVER_H
diff --git a/media/libmediaplayerservice/VorbisPlayer.cpp b/media/libmediaplayerservice/VorbisPlayer.cpp
deleted file mode 100644
index 8181999..0000000
--- a/media/libmediaplayerservice/VorbisPlayer.cpp
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
-** Copyright 2007, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "VorbisPlayer"
-#include "utils/Log.h"
-
-#include <stdio.h>
-#include <assert.h>
-#include <limits.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sched.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-
-#include "VorbisPlayer.h"
-
-#ifdef HAVE_GETTID
-static pid_t myTid() { return gettid(); }
-#else
-static pid_t myTid() { return getpid(); }
-#endif
-
-// ----------------------------------------------------------------------------
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-// TODO: Determine appropriate return codes
-static status_t ERROR_NOT_OPEN = -1;
-static status_t ERROR_OPEN_FAILED = -2;
-static status_t ERROR_ALLOCATE_FAILED = -4;
-static status_t ERROR_NOT_SUPPORTED = -8;
-static status_t ERROR_NOT_READY = -16;
-static status_t STATE_INIT = 0;
-static status_t STATE_ERROR = 1;
-static status_t STATE_OPEN = 2;
-
-
-VorbisPlayer::VorbisPlayer() :
- mAudioBuffer(NULL), mPlayTime(-1), mDuration(-1), mState(STATE_ERROR),
- mStreamType(AudioSystem::MUSIC), mLoop(false), mAndroidLoop(false),
- mExit(false), mPaused(false), mRender(false), mRenderTid(-1)
-{
- LOGV("constructor\n");
- memset(&mVorbisFile, 0, sizeof mVorbisFile);
-}
-
-void VorbisPlayer::onFirstRef()
-{
- LOGV("onFirstRef");
- // create playback thread
- Mutex::Autolock l(mMutex);
- createThreadEtc(renderThread, this, "vorbis decoder", ANDROID_PRIORITY_AUDIO);
- mCondition.wait(mMutex);
- if (mRenderTid > 0) {
- LOGV("render thread(%d) started", mRenderTid);
- mState = STATE_INIT;
- }
-}
-
-status_t VorbisPlayer::initCheck()
-{
- if (mState != STATE_ERROR) return NO_ERROR;
- return ERROR_NOT_READY;
-}
-
-VorbisPlayer::~VorbisPlayer() {
- LOGV("VorbisPlayer destructor\n");
- release();
-}
-
-status_t VorbisPlayer::setDataSource(
- const char *uri, const KeyedVector<String8, String8> *headers) {
- return setdatasource(uri, -1, 0, 0x7ffffffffffffffLL); // intentionally less than LONG_MAX
-}
-
-status_t VorbisPlayer::setDataSource(int fd, int64_t offset, int64_t length)
-{
- return setdatasource(NULL, fd, offset, length);
-}
-
-size_t VorbisPlayer::vp_fread(void *buf, size_t size, size_t nmemb, void *me) {
- VorbisPlayer *self = (VorbisPlayer*) me;
-
- long curpos = vp_ftell(me);
- while (nmemb != 0 && (curpos + size * nmemb) > self->mLength) {
- nmemb--;
- }
- return fread(buf, size, nmemb, self->mFile);
-}
-
-int VorbisPlayer::vp_fseek(void *me, ogg_int64_t off, int whence) {
- VorbisPlayer *self = (VorbisPlayer*) me;
- if (whence == SEEK_SET)
- return fseek(self->mFile, off + self->mOffset, whence);
- else if (whence == SEEK_CUR)
- return fseek(self->mFile, off, whence);
- else if (whence == SEEK_END)
- return fseek(self->mFile, self->mOffset + self->mLength + off, SEEK_SET);
- return -1;
-}
-
-int VorbisPlayer::vp_fclose(void *me) {
- LOGV("vp_fclose");
- VorbisPlayer *self = (VorbisPlayer*) me;
- int ret = fclose (self->mFile);
- self->mFile = NULL;
- return ret;
-}
-
-long VorbisPlayer::vp_ftell(void *me) {
- VorbisPlayer *self = (VorbisPlayer*) me;
- return ftell(self->mFile) - self->mOffset;
-}
-
-status_t VorbisPlayer::setdatasource(const char *path, int fd, int64_t offset, int64_t length)
-{
- LOGV("setDataSource url=%s, fd=%d\n", path, fd);
-
- // file still open?
- Mutex::Autolock l(mMutex);
- if (mState == STATE_OPEN) {
- reset_nosync();
- }
-
- // open file and set paused state
- if (path) {
- mFile = fopen(path, "r");
- } else {
- mFile = fdopen(dup(fd), "r");
- }
- if (mFile == NULL) {
- return ERROR_OPEN_FAILED;
- }
-
- struct stat sb;
- int ret;
- if (path) {
- ret = stat(path, &sb);
- } else {
- ret = fstat(fd, &sb);
- }
- if (ret != 0) {
- mState = STATE_ERROR;
- fclose(mFile);
- return ERROR_OPEN_FAILED;
- }
- if (sb.st_size > (length + offset)) {
- mLength = length;
- } else {
- mLength = sb.st_size - offset;
- }
-
- ov_callbacks callbacks = {
- (size_t (*)(void *, size_t, size_t, void *)) vp_fread,
- (int (*)(void *, ogg_int64_t, int)) vp_fseek,
- (int (*)(void *)) vp_fclose,
- (long (*)(void *)) vp_ftell
- };
-
- mOffset = offset;
- fseek(mFile, offset, SEEK_SET);
-
- int result = ov_open_callbacks(this, &mVorbisFile, NULL, 0, callbacks);
- if (result < 0) {
- LOGE("ov_open() failed: [%d]\n", (int)result);
- mState = STATE_ERROR;
- fclose(mFile);
- return ERROR_OPEN_FAILED;
- }
-
- // look for the android loop tag (for ringtones)
- char **ptr = ov_comment(&mVorbisFile,-1)->user_comments;
- while(*ptr) {
- // does the comment start with ANDROID_LOOP_TAG
- if(strncmp(*ptr, ANDROID_LOOP_TAG, strlen(ANDROID_LOOP_TAG)) == 0) {
- // read the value of the tag
- char *val = *ptr + strlen(ANDROID_LOOP_TAG) + 1;
- mAndroidLoop = (strncmp(val, "true", 4) == 0);
- }
- // we keep parsing even after finding one occurence of ANDROID_LOOP_TAG,
- // as we could find another one (the tag might have been appended more than once).
- ++ptr;
- }
- LOGV_IF(mAndroidLoop, "looped sound");
-
- mState = STATE_OPEN;
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::prepare()
-{
- LOGV("prepare\n");
- if (mState != STATE_OPEN ) {
- return ERROR_NOT_OPEN;
- }
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::prepareAsync() {
- LOGV("prepareAsync\n");
- // can't hold the lock here because of the callback
- // it's safe because we don't change state
- if (mState != STATE_OPEN ) {
- sendEvent(MEDIA_ERROR);
- return NO_ERROR;
- }
- sendEvent(MEDIA_PREPARED);
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::start()
-{
- LOGV("start\n");
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- return ERROR_NOT_OPEN;
- }
-
- mPaused = false;
- mRender = true;
-
- // wake up render thread
- LOGV(" wakeup render thread\n");
- mCondition.signal();
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::stop()
-{
- LOGV("stop\n");
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- return ERROR_NOT_OPEN;
- }
- mPaused = true;
- mRender = false;
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::seekTo(int position)
-{
- LOGV("seekTo %d\n", position);
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- return ERROR_NOT_OPEN;
- }
-
- int result = ov_time_seek(&mVorbisFile, position);
- if (result != 0) {
- LOGE("ov_time_seek() returned %d\n", result);
- return result;
- }
- sendEvent(MEDIA_SEEK_COMPLETE);
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::pause()
-{
- LOGV("pause\n");
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- return ERROR_NOT_OPEN;
- }
- mPaused = true;
- return NO_ERROR;
-}
-
-bool VorbisPlayer::isPlaying()
-{
- LOGV("isPlaying\n");
- if (mState == STATE_OPEN) {
- return mRender;
- }
- return false;
-}
-
-status_t VorbisPlayer::getCurrentPosition(int* position)
-{
- LOGV("getCurrentPosition\n");
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- LOGE("getCurrentPosition(): file not open");
- return ERROR_NOT_OPEN;
- }
- *position = ov_time_tell(&mVorbisFile);
- if (*position < 0) {
- LOGE("getCurrentPosition(): ov_time_tell returned %d", *position);
- return *position;
- }
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::getDuration(int* duration)
-{
- LOGV("getDuration\n");
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- return ERROR_NOT_OPEN;
- }
-
- int ret = ov_time_total(&mVorbisFile, -1);
- if (ret == OV_EINVAL) {
- return -1;
- }
-
- *duration = ret;
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::release()
-{
- LOGV("release\n");
- Mutex::Autolock l(mMutex);
- reset_nosync();
-
- // TODO: timeout when thread won't exit
- // wait for render thread to exit
- if (mRenderTid > 0) {
- mExit = true;
- mCondition.signal();
- mCondition.wait(mMutex);
- }
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::reset()
-{
- LOGV("reset\n");
- Mutex::Autolock l(mMutex);
- return reset_nosync();
-}
-
-// always call with lock held
-status_t VorbisPlayer::reset_nosync()
-{
- // close file
- if (mFile != NULL) {
- ov_clear(&mVorbisFile); // this also closes the FILE
- if (mFile != NULL) {
- LOGV("OOPS! Vorbis didn't close the file");
- fclose(mFile);
- mFile = NULL;
- }
- }
- mState = STATE_ERROR;
-
- mPlayTime = -1;
- mDuration = -1;
- mLoop = false;
- mAndroidLoop = false;
- mPaused = false;
- mRender = false;
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::setLooping(int loop)
-{
- LOGV("setLooping\n");
- Mutex::Autolock l(mMutex);
- mLoop = (loop != 0);
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::createOutputTrack() {
- // open audio track
- vorbis_info *vi = ov_info(&mVorbisFile, -1);
-
- LOGV("Create AudioTrack object: rate=%ld, channels=%d\n",
- vi->rate, vi->channels);
- if (mAudioSink->open(vi->rate, vi->channels, AudioSystem::PCM_16_BIT, DEFAULT_AUDIOSINK_BUFFERCOUNT) != NO_ERROR) {
- LOGE("mAudioSink open failed");
- return ERROR_OPEN_FAILED;
- }
- return NO_ERROR;
-}
-
-int VorbisPlayer::renderThread(void* p) {
- return ((VorbisPlayer*)p)->render();
-}
-
-#define AUDIOBUFFER_SIZE 4096
-
-int VorbisPlayer::render() {
- int result = -1;
- int temp;
- int current_section = 0;
- bool audioStarted = false;
-
- LOGV("render\n");
-
- // allocate render buffer
- mAudioBuffer = new char[AUDIOBUFFER_SIZE];
- if (!mAudioBuffer) {
- LOGE("mAudioBuffer allocate failed\n");
- goto threadExit;
- }
-
- // let main thread know we're ready
- {
- Mutex::Autolock l(mMutex);
- mRenderTid = myTid();
- mCondition.signal();
- }
-
- while (1) {
- long numread = 0;
- {
- Mutex::Autolock l(mMutex);
-
- // pausing?
- if (mPaused) {
- if (mAudioSink->ready()) mAudioSink->pause();
- mRender = false;
- audioStarted = false;
- }
-
- // nothing to render, wait for client thread to wake us up
- if (!mExit && !mRender) {
- LOGV("render - signal wait\n");
- mCondition.wait(mMutex);
- LOGV("render - signal rx'd\n");
- }
- if (mExit) break;
-
- // We could end up here if start() is called, and before we get a
- // chance to run, the app calls stop() or reset(). Re-check render
- // flag so we don't try to render in stop or reset state.
- if (!mRender) continue;
-
- // render vorbis data into the input buffer
- numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, ¤t_section);
- if (numread == 0) {
- // end of file, do we need to loop?
- // ...
- if (mLoop || mAndroidLoop) {
- ov_time_seek(&mVorbisFile, 0);
- current_section = 0;
- numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, ¤t_section);
- } else {
- mAudioSink->stop();
- audioStarted = false;
- mRender = false;
- mPaused = true;
- int endpos = ov_time_tell(&mVorbisFile);
-
- LOGV("send MEDIA_PLAYBACK_COMPLETE");
- sendEvent(MEDIA_PLAYBACK_COMPLETE);
-
- // wait until we're started again
- LOGV("playback complete - wait for signal");
- mCondition.wait(mMutex);
- LOGV("playback complete - signal rx'd");
- if (mExit) break;
-
- // if we're still at the end, restart from the beginning
- if (mState == STATE_OPEN) {
- int curpos = ov_time_tell(&mVorbisFile);
- if (curpos == endpos) {
- ov_time_seek(&mVorbisFile, 0);
- }
- current_section = 0;
- numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, ¤t_section);
- }
- }
- }
- }
-
- // codec returns negative number on error
- if (numread < 0) {
- LOGE("Error in Vorbis decoder");
- sendEvent(MEDIA_ERROR);
- break;
- }
-
- // create audio output track if necessary
- if (!mAudioSink->ready()) {
- LOGV("render - create output track\n");
- if (createOutputTrack() != NO_ERROR)
- break;
- }
-
- // Write data to the audio hardware
- if ((temp = mAudioSink->write(mAudioBuffer, numread)) < 0) {
- LOGE("Error in writing:%d",temp);
- result = temp;
- break;
- }
-
- // start audio output if necessary
- if (!audioStarted && !mPaused && !mExit) {
- LOGV("render - starting audio\n");
- mAudioSink->start();
- audioStarted = true;
- }
- }
-
-threadExit:
- mAudioSink.clear();
- if (mAudioBuffer) {
- delete [] mAudioBuffer;
- mAudioBuffer = NULL;
- }
-
- // tell main thread goodbye
- Mutex::Autolock l(mMutex);
- mRenderTid = -1;
- mCondition.signal();
- return result;
-}
-
-} // end namespace android
diff --git a/media/libmediaplayerservice/VorbisPlayer.h b/media/libmediaplayerservice/VorbisPlayer.h
deleted file mode 100644
index 4a50835..0000000
--- a/media/libmediaplayerservice/VorbisPlayer.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_VORBISPLAYER_H
-#define ANDROID_VORBISPLAYER_H
-
-#include <utils/threads.h>
-
-#include <media/MediaPlayerInterface.h>
-#include <media/AudioTrack.h>
-
-#include "ivorbiscodec.h"
-#include "ivorbisfile.h"
-
-#define ANDROID_LOOP_TAG "ANDROID_LOOP"
-
-namespace android {
-
-class VorbisPlayer : public MediaPlayerInterface {
-public:
- VorbisPlayer();
- ~VorbisPlayer();
-
- virtual void onFirstRef();
- virtual status_t initCheck();
-
- virtual status_t setDataSource(
- const char *uri, const KeyedVector<String8, String8> *headers);
-
- virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
- virtual status_t setVideoSurface(const sp<ISurface>& surface) { return UNKNOWN_ERROR; }
- virtual status_t prepare();
- virtual status_t prepareAsync();
- virtual status_t start();
- virtual status_t stop();
- virtual status_t seekTo(int msec);
- virtual status_t pause();
- virtual bool isPlaying();
- virtual status_t getCurrentPosition(int* msec);
- virtual status_t getDuration(int* msec);
- virtual status_t release();
- virtual status_t reset();
- virtual status_t setLooping(int loop);
- virtual player_type playerType() { return VORBIS_PLAYER; }
- virtual status_t invoke(const Parcel& request, Parcel *reply) {return INVALID_OPERATION;}
-
-private:
- status_t setdatasource(const char *path, int fd, int64_t offset, int64_t length);
- status_t reset_nosync();
- status_t createOutputTrack();
- static int renderThread(void*);
- int render();
-
- static size_t vp_fread(void *, size_t, size_t, void *);
- static int vp_fseek(void *, ogg_int64_t, int);
- static int vp_fclose(void *);
- static long vp_ftell(void *);
-
- Mutex mMutex;
- Condition mCondition;
- FILE* mFile;
- int64_t mOffset;
- int64_t mLength;
- OggVorbis_File mVorbisFile;
- char* mAudioBuffer;
- int mPlayTime;
- int mDuration;
- status_t mState;
- int mStreamType;
- bool mLoop;
- bool mAndroidLoop;
- volatile bool mExit;
- bool mPaused;
- volatile bool mRender;
- pid_t mRenderTid;
-};
-
-}; // namespace android
-
-#endif // ANDROID_VORBISPLAYER_H
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index 8951f5b..6d1dd16 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -97,7 +97,7 @@
return OK;
}
-status_t AMRWriter::start() {
+status_t AMRWriter::start(MetaData *params) {
if (mInitCheck != OK) {
return mInitCheck;
}
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 00a6995..60d0233 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -3,51 +3,44 @@
include frameworks/base/media/libstagefright/codecs/common/Config.mk
-LOCAL_SRC_FILES:= \
- ESDS.cpp \
- MediaBuffer.cpp \
- MediaBufferGroup.cpp \
- MediaDefs.cpp \
- MediaSource.cpp \
- MetaData.cpp \
- OMXCodec.cpp \
- Utils.cpp \
- OMXClient.cpp
-
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
-LOCAL_SRC_FILES += \
- AMRExtractor.cpp \
- AMRWriter.cpp \
- AudioPlayer.cpp \
- AudioSource.cpp \
- AwesomePlayer.cpp \
- CameraSource.cpp \
- DataSource.cpp \
- FileSource.cpp \
- HTTPStream.cpp \
- JPEGSource.cpp \
- MP3Extractor.cpp \
- MPEG4Extractor.cpp \
- MPEG4Writer.cpp \
- MediaExtractor.cpp \
- NuCachedSource2.cpp \
- NuHTTPDataSource.cpp \
- OggExtractor.cpp \
- SampleIterator.cpp \
- SampleTable.cpp \
- ShoutcastSource.cpp \
- StagefrightMediaScanner.cpp \
- StagefrightMetadataRetriever.cpp \
- ThrottledSource.cpp \
- TimeSource.cpp \
- TimedEventQueue.cpp \
- WAVExtractor.cpp \
+LOCAL_SRC_FILES:= \
+ AMRExtractor.cpp \
+ AMRWriter.cpp \
+ AudioPlayer.cpp \
+ AudioSource.cpp \
+ AwesomePlayer.cpp \
+ CameraSource.cpp \
+ DataSource.cpp \
+ ESDS.cpp \
+ FileSource.cpp \
+ HTTPStream.cpp \
+ JPEGSource.cpp \
+ MP3Extractor.cpp \
+ MPEG4Extractor.cpp \
+ MPEG4Writer.cpp \
+ MediaBuffer.cpp \
+ MediaBufferGroup.cpp \
+ MediaDefs.cpp \
+ MediaExtractor.cpp \
+ MediaSource.cpp \
+ MetaData.cpp \
+ NuCachedSource2.cpp \
+ NuHTTPDataSource.cpp \
+ OMXClient.cpp \
+ OMXCodec.cpp \
+ OggExtractor.cpp \
+ SampleIterator.cpp \
+ SampleTable.cpp \
+ ShoutcastSource.cpp \
+ StagefrightMediaScanner.cpp \
+ StagefrightMetadataRetriever.cpp \
+ ThrottledSource.cpp \
+ TimeSource.cpp \
+ TimedEventQueue.cpp \
+ Utils.cpp \
+ WAVExtractor.cpp \
string.cpp
-LOCAL_CFLAGS += -DBUILD_WITH_FULL_STAGEFRIGHT
-endif
-
LOCAL_C_INCLUDES:= \
$(JNI_H_INCLUDE) \
$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
@@ -82,20 +75,13 @@
libstagefright_mpeg2ts \
libstagefright_httplive \
libstagefright_rtsp \
+ libstagefright_id3 \
LOCAL_SHARED_LIBRARIES += \
libstagefright_amrnb_common \
libstagefright_enc_common \
libstagefright_avc_common \
libstagefright_foundation \
-
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
-
-LOCAL_STATIC_LIBRARIES += \
- libstagefright_id3
-
-LOCAL_SHARED_LIBRARIES += \
libstagefright_color_conversion
ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
@@ -108,8 +94,6 @@
LOCAL_SHARED_LIBRARIES += libdl
endif
-endif
-
ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
LOCAL_LDLIBS += -lpthread
endif
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index d203dbf..6031797 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -78,6 +78,8 @@
mCollectStats = true;
}
+ mTrackMaxAmplitude = false;
+ mMaxAmplitude = 0;
mStartTimeUs = 0;
int64_t startTimeUs;
if (params && params->findInt64(kKeyTime, &startTimeUs)) {
@@ -168,6 +170,10 @@
return (status_t)n;
}
+ if (mTrackMaxAmplitude) {
+ trackMaxAmplitude((int16_t *) buffer->data(), n >> 1);
+ }
+
uint32_t sampleRate = mRecord->getSampleRate();
int64_t timestampUs = (1000000LL * numFramesRecorded) / sampleRate + mStartTimeUs;
buffer->meta_data()->setInt64(kKeyTime, timestampUs);
@@ -181,4 +187,27 @@
return OK;
}
+void AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) {
+ for (int i = nSamples; i > 0; --i) {
+ int16_t value = *data++;
+ if (value < 0) {
+ value = -value;
+ }
+ if (mMaxAmplitude < value) {
+ mMaxAmplitude = value;
+ }
+ }
+}
+
+int16_t AudioSource::getMaxAmplitude() {
+ // First call activates the tracking.
+ if (!mTrackMaxAmplitude) {
+ mTrackMaxAmplitude = true;
+ }
+ int16_t value = mMaxAmplitude;
+ mMaxAmplitude = 0;
+ LOGV("max amplitude since last call: %d", value);
+ return value;
+}
+
} // namespace android
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 3639db4..0c2f1e6 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -428,6 +428,14 @@
}
chunk_size = ntoh64(chunk_size);
data_offset += 8;
+
+ if (chunk_size < 16) {
+ // The smallest valid chunk is 16 bytes long in this case.
+ return ERROR_MALFORMED;
+ }
+ } else if (chunk_size < 8) {
+ // The smallest valid chunk is 8 bytes long.
+ return ERROR_MALFORMED;
}
char chunk[5];
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 4242d36..65d109b 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -180,12 +180,73 @@
return OK;
}
-status_t MPEG4Writer::start() {
+int64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
+ // This implementation is highly experimental/heurisitic.
+ //
+ // Statistical analysis shows that metadata usually accounts
+ // for a small portion of the total file size, usually < 0.6%.
+ // Currently, lets set to 0.4% for now.
+
+ // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB,
+ // where 1MB is the common file size limit for MMS application.
+ // The default MAX _MOOV_BOX_SIZE value is based on about 4
+ // minute video recording with a bit rate about 3 Mbps, because
+ // statistics also show that most of the video captured are going
+ // to be less than 3 minutes.
+
+ // If the estimation is wrong, we will pay the price of wasting
+ // some reserved space. This should not happen so often statistically.
+ static const int32_t factor = mUse32BitOffset? 1: 2;
+ static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024; // 4 KB
+ static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
+ int64_t size = MIN_MOOV_BOX_SIZE;
+
+ if (mMaxFileSizeLimitBytes != 0) {
+ size = mMaxFileSizeLimitBytes * 4 / 1000;
+ } else if (mMaxFileDurationLimitUs != 0) {
+ if (bitRate <= 0) {
+ // We could not estimate the file size since bitRate is not set.
+ size = MIN_MOOV_BOX_SIZE;
+ } else {
+ size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000);
+ }
+ }
+ if (size < MIN_MOOV_BOX_SIZE) {
+ size = MIN_MOOV_BOX_SIZE;
+ }
+
+ // Any long duration recording will be probably end up with
+ // non-streamable mp4 file.
+ if (size > MAX_MOOV_BOX_SIZE) {
+ size = MAX_MOOV_BOX_SIZE;
+ }
+
+ LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
+ " moov size %lld bytes",
+ mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
+ return factor * size;
+}
+
+status_t MPEG4Writer::start(MetaData *param) {
if (mFile == NULL) {
return UNKNOWN_ERROR;
}
- mStartTimestampUs = 0;
+ int32_t use64BitOffset;
+ if (param &&
+ param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
+ use64BitOffset) {
+ mUse32BitOffset = false;
+ }
+
+ // System property can overwrite the file offset bits parameter
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.stagefright.record-64bits", value, NULL)
+ && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
+ mUse32BitOffset = false;
+ }
+
+ mStartTimestampUs = -1;
if (mStarted) {
if (mPaused) {
mPaused = false;
@@ -208,9 +269,11 @@
mFreeBoxOffset = mOffset;
if (mEstimatedMoovBoxSize == 0) {
- // XXX: Estimate the moov box size
- // based on max file size or duration limit
- mEstimatedMoovBoxSize = 0x0F00;
+ int32_t bitRate = -1;
+ if (param) {
+ param->findInt32(kKeyBitRate, &bitRate);
+ }
+ mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
}
CHECK(mEstimatedMoovBoxSize >= 8);
fseeko(mFile, mFreeBoxOffset, SEEK_SET);
@@ -332,8 +395,7 @@
write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile);
// Free box
- mFreeBoxOffset = mStreamableFile? mOffset: mFreeBoxOffset;
- fseeko(mFile, mFreeBoxOffset, SEEK_SET);
+ fseeko(mFile, mOffset, SEEK_SET);
writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
write("free", 4);
@@ -341,6 +403,8 @@
free(mMoovBoxBuffer);
mMoovBoxBuffer = NULL;
mMoovBoxBufferOffset = 0;
+ } else {
+ LOGI("The mp4 file will not be streamable.");
}
CHECK(mBoxes.empty());
@@ -561,8 +625,7 @@
LOGI("setStartTimestampUs: %lld", timeUs);
CHECK(timeUs >= 0);
Mutex::Autolock autoLock(mLock);
- if (mStartTimestampUs == 0 ||
- (mStartTimestampUs > 0 && mStartTimestampUs > timeUs)) {
+ if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
mStartTimestampUs = timeUs;
LOGI("Earliest track starting time: %lld", mStartTimestampUs);
}
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 8979c3b..02a073e 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -425,7 +425,6 @@
for (size_t i = 0; i < matchingCodecs.size(); ++i) {
componentName = matchingCodecs[i].string();
-#if BUILD_WITH_FULL_STAGEFRIGHT
sp<MediaSource> softwareCodec = createEncoder?
InstantiateSoftwareEncoder(componentName, source, meta):
InstantiateSoftwareCodec(componentName, source);
@@ -435,7 +434,6 @@
return softwareCodec;
}
-#endif
LOGV("Attempting to allocate OMX node '%s'", componentName);
diff --git a/media/libstagefright/codecs/aacenc/AACEncoder.cpp b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
index 52204fa..b914023 100644
--- a/media/libstagefright/codecs/aacenc/AACEncoder.cpp
+++ b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
@@ -139,6 +139,8 @@
CHECK_EQ(OK, initCheck());
+ mNumInputSamples = 0;
+ mAnchorTimeUs = 0;
mFrameCount = 0;
mSource->start(params);
@@ -205,33 +207,65 @@
buffer->set_range(0, 2);
buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
*out = buffer;
- mInputBuffer = NULL;
++mFrameCount;
return OK;
} else if (mFrameCount == 1) {
buffer->meta_data()->setInt32(kKeyIsCodecConfig, false);
}
- // XXX: We assume that the input buffer contains at least
- // (actually, exactly) 1024 PCM samples. This needs to be fixed.
- if (mInputBuffer == NULL) {
- if (mSource->read(&mInputBuffer, options) != OK) {
- LOGE("failed to read from input audio source");
- return UNKNOWN_ERROR;
+ while (mNumInputSamples < kNumSamplesPerFrame) {
+ if (mInputBuffer == NULL) {
+ if (mSource->read(&mInputBuffer, options) != OK) {
+ if (mNumInputSamples == 0) {
+ return ERROR_END_OF_STREAM;
+ }
+ memset(&mInputFrame[mNumInputSamples],
+ 0,
+ sizeof(int16_t) * (kNumSamplesPerFrame - mNumInputSamples));
+ mNumInputSamples = 0;
+ break;
+ }
+
+ size_t align = mInputBuffer->range_length() % sizeof(int16_t);
+ CHECK_EQ(align, 0);
+
+ int64_t timeUs;
+ if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
+ mAnchorTimeUs = timeUs;
+ }
}
+ size_t copy =
+ (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t);
+
+ if (copy > mInputBuffer->range_length()) {
+ copy = mInputBuffer->range_length();
+ }
+
+ memcpy(&mInputFrame[mNumInputSamples],
+ (const uint8_t *) mInputBuffer->data()
+ + mInputBuffer->range_offset(),
+ copy);
+
+ mInputBuffer->set_range(
+ mInputBuffer->range_offset() + copy,
+ mInputBuffer->range_length() - copy);
+
if (mInputBuffer->range_length() == 0) {
mInputBuffer->release();
mInputBuffer = NULL;
- return ERROR_END_OF_STREAM;
}
- VO_CODECBUFFER inputData;
- memset(&inputData, 0, sizeof(inputData));
- inputData.Buffer = (unsigned char*) mInputBuffer->data();
- inputData.Length = mInputBuffer->range_length();
- CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData));
+ mNumInputSamples += copy / sizeof(int16_t);
+ if (mNumInputSamples >= kNumSamplesPerFrame) {
+ mNumInputSamples %= kNumSamplesPerFrame;
+ break;
+ }
}
- CHECK(mInputBuffer != NULL);
+ VO_CODECBUFFER inputData;
+ memset(&inputData, 0, sizeof(inputData));
+ inputData.Buffer = (unsigned char*) mInputFrame;
+ inputData.Length = kNumSamplesPerFrame * sizeof(int16_t);
+ CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData));
VO_CODECBUFFER outputData;
memset(&outputData, 0, sizeof(outputData));
@@ -239,24 +273,14 @@
memset(&outputInfo, 0, sizeof(outputInfo));
VO_U32 ret = VO_ERR_NONE;
- int32_t outputLength = 0;
outputData.Buffer = outPtr;
outputData.Length = buffer->size();
ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo);
- if (ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL) {
- outputLength += outputData.Length;
- if (ret == VO_ERR_INPUT_BUFFER_SMALL) { // All done
- mInputBuffer->release();
- mInputBuffer = NULL;
- }
- } else {
- LOGE("failed to encode the input data 0x%lx", ret);
- }
+ CHECK(ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL);
+ CHECK(outputData.Length != 0);
+ buffer->set_range(0, outputData.Length);
- buffer->set_range(0, outputLength);
-
- // Each output frame compresses 1024 input PCM samples.
- int64_t timestampUs = ((mFrameCount - 1) * 1000000LL * 1024) / mSampleRate;
+ int64_t timestampUs = ((mFrameCount - 1) * 1000000LL * kNumSamplesPerFrame) / mSampleRate;
++mFrameCount;
buffer->meta_data()->setInt64(kKeyTime, timestampUs);
diff --git a/media/libstagefright/id3/Android.mk b/media/libstagefright/id3/Android.mk
index 93fac1c..23c8e44 100644
--- a/media/libstagefright/id3/Android.mk
+++ b/media/libstagefright/id3/Android.mk
@@ -1,5 +1,3 @@
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -28,5 +26,3 @@
LOCAL_MODULE := testid3
include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/media/libstagefright/include/AACEncoder.h b/media/libstagefright/include/AACEncoder.h
index 211a332..ecc533f 100644
--- a/media/libstagefright/include/AACEncoder.h
+++ b/media/libstagefright/include/AACEncoder.h
@@ -52,6 +52,16 @@
int32_t mChannels;
int32_t mBitRate;
int32_t mFrameCount;
+
+ int64_t mAnchorTimeUs;
+ int64_t mNumInputSamples;
+
+ enum {
+ kNumSamplesPerFrame = 1024,
+ };
+
+ int16_t mInputFrame[kNumSamplesPerFrame];
+
uint8_t mAudioSpecificConfigData[2]; // auido specific data
void *mEncoderHandle;
VO_AUDIO_CODECAPI *mApiHandle;
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index f73e837..3a20c16 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -49,8 +49,8 @@
friend struct AHandlerReflector<NuCachedSource2>;
enum {
- kPageSize = 16384,
- kHighWaterThreshold = 3 * 1024 * 1024,
+ kPageSize = 65536,
+ kHighWaterThreshold = 5 * 1024 * 1024,
kLowWaterThreshold = 512 * 1024,
// Read data after a 15 sec timeout whether we're actively
diff --git a/media/libstagefright/omx/tests/Android.mk b/media/libstagefright/omx/tests/Android.mk
index ee117e5..8bf4336 100644
--- a/media/libstagefright/omx/tests/Android.mk
+++ b/media/libstagefright/omx/tests/Android.mk
@@ -1,5 +1,3 @@
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -17,7 +15,3 @@
LOCAL_MODULE:= omx_tests
include $(BUILD_EXECUTABLE)
-
-endif
-
-
diff --git a/media/tests/omxjpegdecoder/Android.mk b/media/tests/omxjpegdecoder/Android.mk
index b7c18bc..f97f8eb 100644
--- a/media/tests/omxjpegdecoder/Android.mk
+++ b/media/tests/omxjpegdecoder/Android.mk
@@ -11,7 +11,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
LOCAL_PATH:= $(call my-dir)
@@ -54,5 +53,3 @@
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/opengl/java/com/google/android/gles_jni/GLImpl.java b/opengl/java/com/google/android/gles_jni/GLImpl.java
index 30b9325..090c0cb7 100644
--- a/opengl/java/com/google/android/gles_jni/GLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/GLImpl.java
@@ -19,7 +19,7 @@
package com.google.android.gles_jni;
-import android.app.ActivityThread;
+import android.app.AppGlobals;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.os.Build;
@@ -65,7 +65,7 @@
private static boolean allowIndirectBuffers(String appName) {
boolean result = false;
int version = 0;
- IPackageManager pm = ActivityThread.getPackageManager();
+ IPackageManager pm = AppGlobals.getPackageManager();
try {
ApplicationInfo applicationInfo = pm.getApplicationInfo(appName, 0);
if (applicationInfo != null) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 2b4714d..cd4f96d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -952,7 +952,7 @@
int vibrate = 0;
vibrate = AudioService.getValueForVibrateSetting(vibrate,
AudioManager.VIBRATE_TYPE_NOTIFICATION, AudioManager.VIBRATE_SETTING_ON);
- vibrate = AudioService.getValueForVibrateSetting(vibrate,
+ vibrate |= AudioService.getValueForVibrateSetting(vibrate,
AudioManager.VIBRATE_TYPE_RINGER, AudioManager.VIBRATE_SETTING_OFF);
loadSetting(stmt, Settings.System.VIBRATE_ON, vibrate);
} finally {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
index a7e5e31..5d16e93 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
@@ -312,8 +312,45 @@
public void addNotification(IBinder key, StatusBarNotification notification) {
addNotificationViews(key, notification);
- // show the ticker
- tick(notification);
+ boolean immersive = false;
+ try {
+ immersive = ActivityManagerNative.getDefault().isTopActivityImmersive();
+ Slog.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive"));
+ } catch (RemoteException ex) {
+ }
+ if (immersive) {
+ if ((notification.notification.flags & Notification.FLAG_HIGH_PRIORITY) != 0) {
+ Slog.d(TAG, "Presenting high-priority notification in immersive activity");
+ // @@@ special new transient ticker mode
+ /*
+ // 1. Populate mAlertBarView
+
+ ImageView alertIcon = (ImageView) mAlertBarView.findViewById(R.id.alertIcon);
+ TextView alertText = (TextView) mAlertBarView.findViewById(R.id.alertText);
+ alertIcon.setImageDrawable(StatusBarIconView.getIcon(
+ alertIcon.getContext(),
+ iconView.getStatusBarIcon()));
+ alertText.setText(notification.notification.tickerText);
+
+ // 2. Animate mAlertBarView in
+ mAlertBarView.setVisibility(View.VISIBLE);
+
+ // 3. Set alarm to age the notification off (TODO)
+ */
+ }
+ } else if (notification.notification.fullScreenIntent != null) {
+ // not immersive & a full-screen alert should be shown
+ Slog.d(TAG, "Notification has fullScreenIntent and activity is not immersive; sending fullScreenIntent");
+ try {
+ notification.notification.fullScreenIntent.send();
+ } catch (PendingIntent.CanceledException e) {
+ }
+ } else {
+ // usual case: status bar visible & not immersive
+
+ // show the ticker
+ tick(notification);
+ }
// Recalculate the position of the sliding windows and the titles.
setAreThereNotifications();
@@ -989,7 +1026,7 @@
void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
removeNotification(key);
try {
- mBarService.onNotificationError(n.pkg, n.tag, n.id, message);
+ mBarService.onNotificationError(n.pkg, n.tag, n.id, n.uid, n.initialPid, message);
} catch (RemoteException ex) {
// The end is nigh.
}
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 2c388ee..3db5dc1 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -17,8 +17,8 @@
package com.android.server;
import android.app.ActivityManagerNative;
-import android.app.ActivityThread;
import android.app.AlarmManager;
+import android.app.AppGlobals;
import android.app.IActivityManager;
import android.app.IApplicationThread;
import android.app.IBackupAgent;
@@ -399,7 +399,7 @@
public BackupManagerService(Context context) {
mContext = context;
mPackageManager = context.getPackageManager();
- mPackageManagerBinder = ActivityThread.getPackageManager();
+ mPackageManagerBinder = AppGlobals.getPackageManager();
mActivityManager = ActivityManagerNative.getDefault();
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
@@ -1313,7 +1313,7 @@
// If everything actually went through and this is the first time we've
// done a backup, we can now record what the current backup dataset token
// is.
- if ((mCurrentToken == 0) && (status != BackupConstants.TRANSPORT_OK)) {
+ if ((mCurrentToken == 0) && (status == BackupConstants.TRANSPORT_OK)) {
try {
mCurrentToken = mTransport.getCurrentRestoreSet();
} catch (RemoteException e) { /* cannot happen */ }
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 6f44e8e..3e2c122 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -164,16 +164,21 @@
final String pkg;
final String tag;
final int id;
+ final int uid;
+ final int initialPid;
ITransientNotification callback;
int duration;
final Notification notification;
IBinder statusBarKey;
- NotificationRecord(String pkg, String tag, int id, Notification notification)
+ NotificationRecord(String pkg, String tag, int id, int uid, int initialPid,
+ Notification notification)
{
this.pkg = pkg;
this.tag = tag;
this.id = id;
+ this.uid = uid;
+ this.initialPid = initialPid;
this.notification = notification;
}
@@ -304,10 +309,18 @@
}
}
- public void onNotificationError(String pkg, String tag, int id, String message) {
+ public void onNotificationError(String pkg, String tag, int id,
+ int uid, int initialPid, String message) {
Slog.d(TAG, "onNotification error pkg=" + pkg + " tag=" + tag + " id=" + id);
cancelNotification(pkg, tag, id, 0, 0);
- // TODO: Tell the activity manager.
+ long ident = Binder.clearCallingIdentity();
+ try {
+ ActivityManagerNative.getDefault().crashApplication(uid, initialPid, pkg,
+ "Bad notification posted from package " + pkg
+ + ": " + message);
+ } catch (RemoteException e) {
+ }
+ Binder.restoreCallingIdentity(ident);
}
};
@@ -663,6 +676,9 @@
public void enqueueNotificationWithTag(String pkg, String tag, int id,
Notification notification, int[] idOut)
{
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
+
checkIncomingCall(pkg);
// Limit the number of notifications that any given package except the android
@@ -708,7 +724,8 @@
}
synchronized (mNotificationList) {
- NotificationRecord r = new NotificationRecord(pkg, tag, id, notification);
+ NotificationRecord r = new NotificationRecord(pkg, tag, id,
+ callingUid, callingPid, notification);
NotificationRecord old = null;
int index = indexOfNotificationLocked(pkg, tag, id);
@@ -732,7 +749,8 @@
}
if (notification.icon != 0) {
- StatusBarNotification n = new StatusBarNotification(pkg, id, tag, notification);
+ StatusBarNotification n = new StatusBarNotification(pkg, id, tag,
+ r.uid, r.initialPid, notification);
if (old != null && old.statusBarKey != null) {
r.statusBarKey = old.statusBarKey;
long identity = Binder.clearCallingIdentity();
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index 1a16387..4177432 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -85,7 +85,8 @@
void onClearAll();
void onNotificationClick(String pkg, String tag, int id);
void onPanelRevealed();
- void onNotificationError(String pkg, String tag, int id, String message);
+ void onNotificationError(String pkg, String tag, int id,
+ int uid, int initialPid, String message);
}
/**
@@ -293,11 +294,12 @@
mNotificationCallbacks.onNotificationClick(pkg, tag, id);
}
- public void onNotificationError(String pkg, String tag, int id, String message) {
+ public void onNotificationError(String pkg, String tag, int id,
+ int uid, int initialPid, String message) {
enforceStatusBarService();
// WARNING: this will call back into us to do the remove. Don't hold any locks.
- mNotificationCallbacks.onNotificationError(pkg, tag, id, message);
+ mNotificationCallbacks.onNotificationError(pkg, tag, id, uid, initialPid, message);
}
public void onClearAllNotifications() {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index b91bf73..7130636 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -96,6 +96,7 @@
BluetoothA2dpService bluetoothA2dp = null;
HeadsetObserver headset = null;
DockObserver dock = null;
+ UsbObserver usb = null;
UiModeManagerService uiMode = null;
RecognitionManagerService recognition = null;
ThrottleService throttle = null;
@@ -373,8 +374,16 @@
}
try {
+ Slog.i(TAG, "USB Observer");
+ // Listen for USB changes
+ usb = new UsbObserver(context);
+ } catch (Throwable e) {
+ Slog.e(TAG, "Failure starting UsbObserver", e);
+ }
+
+ try {
Slog.i(TAG, "UI Mode Manager Service");
- // Listen for dock station changes
+ // Listen for UI mode changes
uiMode = new UiModeManagerService(context);
} catch (Throwable e) {
Slog.e(TAG, "Failure starting UiModeManagerService", e);
@@ -461,6 +470,7 @@
final BatteryService batteryF = battery;
final ConnectivityService connectivityF = connectivity;
final DockObserver dockF = dock;
+ final UsbObserver usbF = usb;
final ThrottleService throttleF = throttle;
final UiModeManagerService uiModeF = uiMode;
final AppWidgetService appWidgetF = appWidget;
@@ -483,6 +493,7 @@
if (batteryF != null) batteryF.systemReady();
if (connectivityF != null) connectivityF.systemReady();
if (dockF != null) dockF.systemReady();
+ if (usbF != null) usbF.systemReady();
if (uiModeF != null) uiModeF.systemReady();
if (recognitionF != null) recognitionF.systemReady();
Watchdog.getInstance().start();
diff --git a/services/java/com/android/server/UsbObserver.java b/services/java/com/android/server/UsbObserver.java
new file mode 100644
index 0000000..3993a7f
--- /dev/null
+++ b/services/java/com/android/server/UsbObserver.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.hardware.Usb;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
+import android.os.UEventObserver;
+import android.provider.Settings;
+import android.util.Log;
+import android.util.Slog;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.util.ArrayList;
+
+/**
+ * <p>UsbObserver monitors for changes to USB state.
+ */
+class UsbObserver extends UEventObserver {
+ private static final String TAG = UsbObserver.class.getSimpleName();
+ private static final boolean LOG = false;
+
+ private static final String USB_CONFIGURATION_MATCH = "DEVPATH=/devices/virtual/switch/usb_configuration";
+ private static final String USB_FUNCTIONS_MATCH = "DEVPATH=/devices/virtual/usb_composite/";
+ private static final String USB_CONFIGURATION_PATH = "/sys/class/switch/usb_configuration/state";
+ private static final String USB_COMPOSITE_CLASS_PATH = "/sys/class/usb_composite";
+
+ private static final int MSG_UPDATE = 0;
+
+ private int mUsbConfig = 0;
+ private int mPreviousUsbConfig = 0;
+
+ // lists of enabled and disabled USB functions
+ private final ArrayList<String> mEnabledFunctions = new ArrayList<String>();
+ private final ArrayList<String> mDisabledFunctions = new ArrayList<String>();
+
+ private boolean mSystemReady;
+
+ private final Context mContext;
+
+ private PowerManagerService mPowerManager;
+
+ public UsbObserver(Context context) {
+ mContext = context;
+ init(); // set initial status
+
+ startObserving(USB_CONFIGURATION_MATCH);
+ startObserving(USB_FUNCTIONS_MATCH);
+ }
+
+ @Override
+ public void onUEvent(UEventObserver.UEvent event) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Slog.v(TAG, "USB UEVENT: " + event.toString());
+ }
+
+ synchronized (this) {
+ String switchState = event.get("SWITCH_STATE");
+ if (switchState != null) {
+ try {
+ int newConfig = Integer.parseInt(switchState);
+ if (newConfig != mUsbConfig) {
+ mPreviousUsbConfig = mUsbConfig;
+ mUsbConfig = newConfig;
+ // trigger an Intent broadcast
+ if (mSystemReady) {
+ update();
+ }
+ }
+ } catch (NumberFormatException e) {
+ Slog.e(TAG, "Could not parse switch state from event " + event);
+ }
+ } else {
+ String function = event.get("FUNCTION");
+ String enabledStr = event.get("ENABLED");
+ if (function != null && enabledStr != null) {
+ // Note: we do not broadcast a change when a function is enabled or disabled.
+ // We just record the state change for the next broadcast.
+ boolean enabled = "1".equals(enabledStr);
+ if (enabled) {
+ if (!mEnabledFunctions.contains(function)) {
+ mEnabledFunctions.add(function);
+ }
+ mDisabledFunctions.remove(function);
+ } else {
+ if (!mDisabledFunctions.contains(function)) {
+ mDisabledFunctions.add(function);
+ }
+ mEnabledFunctions.remove(function);
+ }
+ }
+ }
+ }
+ }
+ private final void init() {
+ char[] buffer = new char[1024];
+
+ try {
+ FileReader file = new FileReader(USB_CONFIGURATION_PATH);
+ int len = file.read(buffer, 0, 1024);
+ mPreviousUsbConfig = mUsbConfig = Integer.valueOf((new String(buffer, 0, len)).trim());
+
+ } catch (FileNotFoundException e) {
+ Slog.w(TAG, "This kernel does not have USB configuration switch support");
+ } catch (Exception e) {
+ Slog.e(TAG, "" , e);
+ }
+
+ try {
+ File[] files = new File(USB_COMPOSITE_CLASS_PATH).listFiles();
+ for (int i = 0; i < files.length; i++) {
+ File file = new File(files[i], "enable");
+ FileReader reader = new FileReader(file);
+ int len = reader.read(buffer, 0, 1024);
+ int value = Integer.valueOf((new String(buffer, 0, len)).trim());
+ String functionName = files[i].getName();
+ if (value == 1) {
+ mEnabledFunctions.add(functionName);
+ } else {
+ mDisabledFunctions.add(functionName);
+ }
+ }
+ } catch (FileNotFoundException e) {
+ Slog.w(TAG, "This kernel does not have USB composite class support");
+ } catch (Exception e) {
+ Slog.e(TAG, "" , e);
+ }
+ }
+
+ void systemReady() {
+ synchronized (this) {
+ update();
+ mSystemReady = true;
+ }
+ }
+
+ private final void update() {
+ mHandler.sendEmptyMessage(MSG_UPDATE);
+ }
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE:
+ synchronized (this) {
+ final ContentResolver cr = mContext.getContentResolver();
+
+ if (Settings.Secure.getInt(cr,
+ Settings.Secure.DEVICE_PROVISIONED, 0) == 0) {
+ Slog.i(TAG, "Device not provisioned, skipping USB broadcast");
+ return;
+ }
+ // Send an Intent containing connected/disconnected state
+ // and the enabled/disabled state of all USB functions
+ Intent intent;
+ if (mUsbConfig != 0) {
+ intent = new Intent(Usb.ACTION_USB_CONNECTED);
+
+ // include state of all USB functions in our extras
+ for (int i = 0; i < mEnabledFunctions.size(); i++) {
+ intent.putExtra(mEnabledFunctions.get(i), Usb.USB_FUNCTION_ENABLED);
+ }
+ for (int i = 0; i < mDisabledFunctions.size(); i++) {
+ intent.putExtra(mDisabledFunctions.get(i), Usb.USB_FUNCTION_DISABLED);
+ }
+ } else {
+ intent = new Intent(Usb.ACTION_USB_DISCONNECTED);
+ }
+
+ mContext.sendBroadcast(intent, android.Manifest.permission.ACCESS_USB);
+ }
+ break;
+ }
+ }
+ };
+}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index d59ecdd..252392b 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -34,6 +34,7 @@
import android.app.ActivityManagerNative;
import android.app.ActivityThread;
import android.app.AlertDialog;
+import android.app.AppGlobals;
import android.app.ApplicationErrorReport;
import android.app.Dialog;
import android.app.IActivityController;
@@ -410,8 +411,8 @@
* due to app switches being disabled.
*/
class PendingActivityLaunch {
- HistoryRecord r;
- HistoryRecord sourceRecord;
+ ActivityRecord r;
+ ActivityRecord sourceRecord;
Uri[] grantedUriPermissions;
int grantedMode;
boolean onlyIfNeeded;
@@ -471,47 +472,47 @@
* When we are in the process of pausing an activity, before starting the
* next one, this variable holds the activity that is currently being paused.
*/
- HistoryRecord mPausingActivity = null;
+ ActivityRecord mPausingActivity = null;
/**
* Current activity that is resumed, or null if there is none.
*/
- HistoryRecord mResumedActivity = null;
+ ActivityRecord mResumedActivity = null;
/**
* Activity we have told the window manager to have key focus.
*/
- HistoryRecord mFocusedActivity = null;
+ ActivityRecord mFocusedActivity = null;
/**
* This is the last activity that we put into the paused state. This is
* used to determine if we need to do an activity transition while sleeping,
* when we normally hold the top activity paused.
*/
- HistoryRecord mLastPausedActivity = null;
+ ActivityRecord mLastPausedActivity = null;
/**
* List of activities that are waiting for a new activity
* to become visible before completing whatever operation they are
* supposed to do.
*/
- final ArrayList<HistoryRecord> mWaitingVisibleActivities
- = new ArrayList<HistoryRecord>();
+ final ArrayList<ActivityRecord> mWaitingVisibleActivities
+ = new ArrayList<ActivityRecord>();
/**
* List of activities that are ready to be stopped, but waiting
* for the next activity to settle down before doing so. It contains
* HistoryRecord objects.
*/
- final ArrayList<HistoryRecord> mStoppingActivities
- = new ArrayList<HistoryRecord>();
+ final ArrayList<ActivityRecord> mStoppingActivities
+ = new ArrayList<ActivityRecord>();
/**
* Animations that for the current transition have requested not to
* be considered for the transition animation.
*/
- final ArrayList<HistoryRecord> mNoAnimActivities
- = new ArrayList<HistoryRecord>();
+ final ArrayList<ActivityRecord> mNoAnimActivities
+ = new ArrayList<ActivityRecord>();
/**
* List of intents that were used to start the most recent tasks.
@@ -524,8 +525,8 @@
* for the previous activity to settle down before doing so. It contains
* HistoryRecord objects.
*/
- final ArrayList<HistoryRecord> mFinishingActivities
- = new ArrayList<HistoryRecord>();
+ final ArrayList<ActivityRecord> mFinishingActivities
+ = new ArrayList<ActivityRecord>();
/**
* All of the applications we currently have running organized by name.
@@ -1096,7 +1097,7 @@
false, false, MY_PID, Process.SYSTEM_UID);
Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
- mContext, proc, (HistoryRecord)data.get("activity"));
+ mContext, proc, (ActivityRecord)data.get("activity"));
d.show();
proc.anrDialog = d;
}
@@ -1310,7 +1311,7 @@
return;
}
- HistoryRecord root = (HistoryRecord)msg.obj;
+ ActivityRecord root = (ActivityRecord)msg.obj;
ProcessRecord process = root.app;
if (process == null) {
return;
@@ -1716,7 +1717,7 @@
return mAppBindArgs;
}
- private final void setFocusedActivityLocked(HistoryRecord r) {
+ private final void setFocusedActivityLocked(ActivityRecord r) {
if (mFocusedActivity != r) {
mFocusedActivity = r;
mWindowManager.setFocusedApp(r, true);
@@ -1807,16 +1808,16 @@
updateLruProcessInternalLocked(app, oomAdj, updateActivityTime, 0);
}
- private final boolean updateLRUListLocked(HistoryRecord r) {
+ private final boolean updateLRUListLocked(ActivityRecord r) {
final boolean hadit = mLRUActivities.remove(r);
mLRUActivities.add(r);
return hadit;
}
- private final HistoryRecord topRunningActivityLocked(HistoryRecord notTop) {
+ private final ActivityRecord topRunningActivityLocked(ActivityRecord notTop) {
int i = mHistory.size()-1;
while (i >= 0) {
- HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
if (!r.finishing && r != notTop) {
return r;
}
@@ -1825,10 +1826,10 @@
return null;
}
- private final HistoryRecord topRunningNonDelayedActivityLocked(HistoryRecord notTop) {
+ private final ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
int i = mHistory.size()-1;
while (i >= 0) {
- HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
if (!r.finishing && !r.delayedResume && r != notTop) {
return r;
}
@@ -1846,10 +1847,10 @@
*
* @return Returns the HistoryRecord of the next activity on the stack.
*/
- private final HistoryRecord topRunningActivityLocked(IBinder token, int taskId) {
+ private final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
int i = mHistory.size()-1;
while (i >= 0) {
- HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
// Note: the taskId check depends on real taskId fields being non-zero
if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
return r;
@@ -1874,7 +1875,7 @@
}
private void ensurePackageDexOpt(String packageName) {
- IPackageManager pm = ActivityThread.getPackageManager();
+ IPackageManager pm = AppGlobals.getPackageManager();
try {
if (pm.performDexOpt(packageName)) {
mDidDexOpt = true;
@@ -1890,7 +1891,7 @@
|| transit == WindowManagerPolicy.TRANSIT_TASK_TO_FRONT;
}
- private final boolean realStartActivityLocked(HistoryRecord r,
+ private final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
@@ -2019,7 +2020,7 @@
return true;
}
- private final void startSpecificActivityLocked(HistoryRecord r,
+ private final void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = getProcessRecordLocked(r.processName,
@@ -2258,7 +2259,7 @@
Slog.e(TAG, "Trying to pause when pause is already pending for "
+ mPausingActivity, e);
}
- HistoryRecord prev = mResumedActivity;
+ ActivityRecord prev = mResumedActivity;
if (prev == null) {
RuntimeException e = new RuntimeException();
Slog.e(TAG, "Trying to pause when nothing is resumed", e);
@@ -2333,7 +2334,7 @@
}
private final void completePauseLocked() {
- HistoryRecord prev = mPausingActivity;
+ ActivityRecord prev = mPausingActivity;
if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
if (prev != null) {
@@ -2415,7 +2416,7 @@
* the resumed state (either by launching it or explicitly telling it),
* this function updates the rest of our state to match that fact.
*/
- private final void completeResumeLocked(HistoryRecord next) {
+ private final void completeResumeLocked(ActivityRecord next) {
next.idle = false;
next.results = null;
next.newIntents = null;
@@ -2460,8 +2461,8 @@
* Make sure that all activities that need to be visible (that is, they
* currently can be seen by the user) actually are.
*/
- private final void ensureActivitiesVisibleLocked(HistoryRecord top,
- HistoryRecord starting, String onlyThisProcess, int configChanges) {
+ private final void ensureActivitiesVisibleLocked(ActivityRecord top,
+ ActivityRecord starting, String onlyThisProcess, int configChanges) {
if (DEBUG_VISBILITY) Slog.v(
TAG, "ensureActivitiesVisible behind " + top
+ " configChanges=0x" + Integer.toHexString(configChanges));
@@ -2473,10 +2474,10 @@
while (mHistory.get(i) != top) {
i--;
}
- HistoryRecord r;
+ ActivityRecord r;
boolean behindFullscreen = false;
for (; i>=0; i--) {
- r = (HistoryRecord)mHistory.get(i);
+ r = (ActivityRecord)mHistory.get(i);
if (DEBUG_VISBILITY) Slog.v(
TAG, "Make visible? " + r + " finishing=" + r.finishing
+ " state=" + r.state);
@@ -2559,7 +2560,7 @@
// Now for any activities that aren't visible to the user, make
// sure they no longer are keeping the screen frozen.
while (i >= 0) {
- r = (HistoryRecord)mHistory.get(i);
+ r = (ActivityRecord)mHistory.get(i);
if (DEBUG_VISBILITY) Slog.v(
TAG, "Make invisible? " + r + " finishing=" + r.finishing
+ " state=" + r.state
@@ -2602,15 +2603,15 @@
/**
* Version of ensureActivitiesVisible that can easily be called anywhere.
*/
- private final void ensureActivitiesVisibleLocked(HistoryRecord starting,
+ private final void ensureActivitiesVisibleLocked(ActivityRecord starting,
int configChanges) {
- HistoryRecord r = topRunningActivityLocked(null);
+ ActivityRecord r = topRunningActivityLocked(null);
if (r != null) {
ensureActivitiesVisibleLocked(r, starting, null, configChanges);
}
}
- private void updateUsageStats(HistoryRecord resumedComponent, boolean resumed) {
+ private void updateUsageStats(ActivityRecord resumedComponent, boolean resumed) {
if (resumed) {
mUsageStatsService.noteResumeComponent(resumedComponent.realActivity);
} else {
@@ -2708,7 +2709,7 @@
}
}
- private void reportResumedActivityLocked(HistoryRecord r) {
+ private void reportResumedActivityLocked(ActivityRecord r) {
//Slog.i(TAG, "**** REPORT RESUME: " + r);
final int identHash = System.identityHashCode(r);
@@ -2737,9 +2738,9 @@
* @return Returns true if something is being resumed, or false if
* nothing happened.
*/
- private final boolean resumeTopActivityLocked(HistoryRecord prev) {
+ private final boolean resumeTopActivityLocked(ActivityRecord prev) {
// Find the first activity that is not finishing.
- HistoryRecord next = topRunningActivityLocked(null);
+ ActivityRecord next = topRunningActivityLocked(null);
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
@@ -2873,7 +2874,7 @@
// This activity is now becoming visible.
mWindowManager.setAppVisibility(next, true);
- HistoryRecord lastResumedActivity = mResumedActivity;
+ ActivityRecord lastResumedActivity = mResumedActivity;
ActivityState lastState = next.state;
updateCpuStats();
@@ -2902,7 +2903,7 @@
// We should be all done, but let's just make sure our activity
// is still at the top and schedule another run if something
// weird happened.
- HistoryRecord nextNext = topRunningActivityLocked(null);
+ ActivityRecord nextNext = topRunningActivityLocked(null);
if (DEBUG_SWITCH) Slog.i(TAG,
"Activity config changed during resume: " + next
+ ", new next: " + nextNext);
@@ -3000,7 +3001,7 @@
return true;
}
- private final void startActivityLocked(HistoryRecord r, boolean newTask,
+ private final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume) {
final int NH = mHistory.size();
@@ -3008,10 +3009,10 @@
if (!newTask) {
// If starting in an existing task, find where that is...
- HistoryRecord next = null;
+ ActivityRecord next = null;
boolean startIt = true;
for (int i = NH-1; i >= 0; i--) {
- HistoryRecord p = (HistoryRecord)mHistory.get(i);
+ ActivityRecord p = (ActivityRecord)mHistory.get(i);
if (p.finishing) {
continue;
}
@@ -3105,7 +3106,7 @@
// "has the same starting icon" as the next one. This allows the
// window manager to keep the previous window it had previously
// created, if it still had one.
- HistoryRecord prev = mResumedActivity;
+ ActivityRecord prev = mResumedActivity;
if (prev != null) {
// We don't want to reuse the previous starting preview if:
// (1) The current activity is in a different task.
@@ -3143,14 +3144,14 @@
* @return Returns the old activity that should be continue to be used,
* or null if none was found.
*/
- private final HistoryRecord performClearTaskLocked(int taskId,
- HistoryRecord newR, int launchFlags, boolean doClear) {
+ private final ActivityRecord performClearTaskLocked(int taskId,
+ ActivityRecord newR, int launchFlags, boolean doClear) {
int i = mHistory.size();
// First find the requested task.
while (i > 0) {
i--;
- HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
if (r.task.taskId == taskId) {
i++;
break;
@@ -3160,7 +3161,7 @@
// Now clear it.
while (i > 0) {
i--;
- HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
if (r.finishing) {
continue;
}
@@ -3169,11 +3170,11 @@
}
if (r.realActivity.equals(newR.realActivity)) {
// Here it is! Now finish everything in front...
- HistoryRecord ret = r;
+ ActivityRecord ret = r;
if (doClear) {
while (i < (mHistory.size()-1)) {
i++;
- r = (HistoryRecord)mHistory.get(i);
+ r = (ActivityRecord)mHistory.get(i);
if (r.finishing) {
continue;
}
@@ -3210,11 +3211,11 @@
* Find the activity in the history stack within the given task. Returns
* the index within the history at which it's found, or < 0 if not found.
*/
- private final int findActivityInHistoryLocked(HistoryRecord r, int task) {
+ private final int findActivityInHistoryLocked(ActivityRecord r, int task) {
int i = mHistory.size();
while (i > 0) {
i--;
- HistoryRecord candidate = (HistoryRecord)mHistory.get(i);
+ ActivityRecord candidate = (ActivityRecord)mHistory.get(i);
if (candidate.task.taskId != task) {
break;
}
@@ -3230,10 +3231,10 @@
* Reorder the history stack so that the activity at the given index is
* brought to the front.
*/
- private final HistoryRecord moveActivityToFrontLocked(int where) {
- HistoryRecord newTop = (HistoryRecord)mHistory.remove(where);
+ private final ActivityRecord moveActivityToFrontLocked(int where) {
+ ActivityRecord newTop = (ActivityRecord)mHistory.remove(where);
int top = mHistory.size();
- HistoryRecord oldTop = (HistoryRecord)mHistory.get(top-1);
+ ActivityRecord oldTop = (ActivityRecord)mHistory.get(top-1);
mHistory.add(top, newTop);
oldTop.frontOfTask = false;
newTop.frontOfTask = true;
@@ -3244,7 +3245,7 @@
* Deliver a new Intent to an existing activity, so that its onNewIntent()
* method will be called at the proper time.
*/
- private final void deliverNewIntentLocked(HistoryRecord r, Intent intent) {
+ private final void deliverNewIntentLocked(ActivityRecord r, Intent intent) {
boolean sent = false;
if (r.state == ActivityState.RESUMED
&& r.app != null && r.app.thread != null) {
@@ -3262,7 +3263,7 @@
}
}
- private final void logStartActivity(int tag, HistoryRecord r,
+ private final void logStartActivity(int tag, ActivityRecord r,
TaskRecord task) {
EventLog.writeEvent(tag,
System.identityHashCode(r), task.taskId,
@@ -3280,14 +3281,14 @@
boolean componentSpecified) {
Slog.i(TAG, "Starting activity: " + intent);
- HistoryRecord sourceRecord = null;
- HistoryRecord resultRecord = null;
+ ActivityRecord sourceRecord = null;
+ ActivityRecord resultRecord = null;
if (resultTo != null) {
int index = indexOfTokenLocked(resultTo);
if (DEBUG_RESULTS) Slog.v(
TAG, "Sending result to " + resultTo + " (index " + index + ")");
if (index >= 0) {
- sourceRecord = (HistoryRecord)mHistory.get(index);
+ sourceRecord = (ActivityRecord)mHistory.get(index);
if (requestCode >= 0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;
}
@@ -3390,7 +3391,7 @@
}
}
- HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
+ ActivityRecord r = new ActivityRecord(this, callerApp, callingUid,
intent, resolvedType, aInfo, mConfiguration,
resultRecord, resultWho, requestCode, componentSpecified);
@@ -3439,8 +3440,8 @@
mPendingActivityLaunches.clear();
}
- private final int startActivityUncheckedLocked(HistoryRecord r,
- HistoryRecord sourceRecord, Uri[] grantedUriPermissions,
+ private final int startActivityUncheckedLocked(ActivityRecord r,
+ ActivityRecord sourceRecord, Uri[] grantedUriPermissions,
int grantedMode, boolean onlyIfNeeded, boolean doResume) {
final Intent intent = r.intent;
final int callingUid = r.launchedFromUid;
@@ -3460,7 +3461,7 @@
r.delayedResume = true;
}
- HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
+ ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
!= 0 ? r : null;
// If the onlyIfNeeded flag is set, then we can do this if the activity
@@ -3468,7 +3469,7 @@
// a special case, if we do not know the caller then we count the
// current top activity as the caller.
if (onlyIfNeeded) {
- HistoryRecord checkedCaller = sourceRecord;
+ ActivityRecord checkedCaller = sourceRecord;
if (checkedCaller == null) {
checkedCaller = topRunningNonDelayedActivityLocked(notTop);
}
@@ -3534,7 +3535,7 @@
// a SINGLE_INSTANCE activity, there can be one and only one
// instance of it in the history, and it is always in its own
// unique task, so we do a special search.
- HistoryRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
+ ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
? findTaskLocked(intent, r.info)
: findActivityLocked(intent, r.info);
if (taskTop != null) {
@@ -3551,7 +3552,7 @@
// to have the same behavior as if a new instance was
// being started, which means not bringing it to the front
// if the caller is not itself in the front.
- HistoryRecord curTop = topRunningNonDelayedActivityLocked(notTop);
+ ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop);
if (curTop.task != taskTop.task) {
r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
boolean callerAtFront = sourceRecord == null
@@ -3584,7 +3585,7 @@
// from the task up to the one being started. In most
// cases this means we are resetting the task to its
// initial state.
- HistoryRecord top = performClearTaskLocked(
+ ActivityRecord top = performClearTaskLocked(
taskTop.task.taskId, r, launchFlags, true);
if (top != null) {
if (top.frontOfTask) {
@@ -3669,7 +3670,7 @@
// If the activity being launched is the same as the one currently
// at the top, then we need to check if it should only be launched
// once.
- HistoryRecord top = topRunningNonDelayedActivityLocked(notTop);
+ ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);
if (top != null && r.resultTo == null) {
if (top.realActivity.equals(r.realActivity)) {
if (top.app != null && top.app.thread != null) {
@@ -3727,7 +3728,7 @@
// In this case, we are adding the activity to an existing
// task, but the caller has asked to clear that task if the
// activity is already running.
- HistoryRecord top = performClearTaskLocked(
+ ActivityRecord top = performClearTaskLocked(
sourceRecord.task.taskId, r, launchFlags, true);
if (top != null) {
logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
@@ -3746,7 +3747,7 @@
// we want to shuffle it to the front of the stack if so.
int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
if (where >= 0) {
- HistoryRecord top = moveActivityToFrontLocked(where);
+ ActivityRecord top = moveActivityToFrontLocked(where);
logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
deliverNewIntentLocked(top, r.intent);
if (doResume) {
@@ -3767,8 +3768,8 @@
// of a new task... just put it in the top task, though these days
// this case should never happen.
final int N = mHistory.size();
- HistoryRecord prev =
- N > 0 ? (HistoryRecord)mHistory.get(N-1) : null;
+ ActivityRecord prev =
+ N > 0 ? (ActivityRecord)mHistory.get(N-1) : null;
r.task = prev != null
? prev.task
: new TaskRecord(mCurTask, r.info, intent,
@@ -3784,7 +3785,7 @@
return START_SUCCESS;
}
- void reportActivityLaunchedLocked(boolean timeout, HistoryRecord r,
+ void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
long thisTime, long totalTime) {
for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
WaitResult w = mWaitingActivityLaunched.get(i);
@@ -3798,7 +3799,7 @@
notify();
}
- void reportActivityVisibleLocked(HistoryRecord r) {
+ void reportActivityVisibleLocked(ActivityRecord r) {
for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
WaitResult w = mWaitingActivityVisible.get(i);
w.timeout = false;
@@ -3830,7 +3831,7 @@
ActivityInfo aInfo;
try {
ResolveInfo rInfo =
- ActivityThread.getPackageManager().resolveIntent(
+ AppGlobals.getPackageManager().resolveIntent(
intent, resolvedType,
PackageManager.MATCH_DEFAULT_ONLY
| STOCK_PM_FLAGS);
@@ -3908,7 +3909,7 @@
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
new IntentSender(target));
if (mHeavyWeightProcess.activities.size() > 0) {
- HistoryRecord hist = mHeavyWeightProcess.activities.get(0);
+ ActivityRecord hist = mHeavyWeightProcess.activities.get(0);
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
hist.packageName);
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
@@ -3927,7 +3928,7 @@
componentSpecified = true;
try {
ResolveInfo rInfo =
- ActivityThread.getPackageManager().resolveIntent(
+ AppGlobals.getPackageManager().resolveIntent(
intent, null,
PackageManager.MATCH_DEFAULT_ONLY
| STOCK_PM_FLAGS);
@@ -3970,7 +3971,7 @@
}
} while (!outResult.timeout && outResult.who == null);
} else if (res == IActivityManager.START_TASK_TO_FRONT) {
- HistoryRecord r = this.topRunningActivityLocked(null);
+ ActivityRecord r = this.topRunningActivityLocked(null);
if (r.nowVisible) {
outResult.timeout = false;
outResult.who = new ComponentName(r.info.packageName, r.info.name);
@@ -4067,7 +4068,7 @@
if (index < 0) {
return false;
}
- HistoryRecord r = (HistoryRecord)mHistory.get(index);
+ ActivityRecord r = (ActivityRecord)mHistory.get(index);
if (r.app == null || r.app.thread == null) {
// The caller is not running... d'oh!
return false;
@@ -4081,7 +4082,7 @@
ActivityInfo aInfo = null;
try {
List<ResolveInfo> resolves =
- ActivityThread.getPackageManager().queryIntentActivities(
+ AppGlobals.getPackageManager().queryIntentActivities(
intent, r.resolvedType,
PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
@@ -4125,7 +4126,7 @@
r.finishing = true;
// Propagate reply information over to the new activity.
- final HistoryRecord resultTo = r.resultTo;
+ final ActivityRecord resultTo = r.resultTo;
final String resultWho = r.resultWho;
final int requestCode = r.requestCode;
r.resultTo = null;
@@ -4170,7 +4171,7 @@
ActivityInfo aInfo;
try {
ResolveInfo rInfo =
- ActivityThread.getPackageManager().resolveIntent(
+ AppGlobals.getPackageManager().resolveIntent(
intent, resolvedType,
PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS);
aInfo = rInfo != null ? rInfo.activityInfo : null;
@@ -4224,7 +4225,7 @@
if (index < 0) {
return;
}
- HistoryRecord r = (HistoryRecord)mHistory.get(index);
+ ActivityRecord r = (ActivityRecord)mHistory.get(index);
final long origId = Binder.clearCallingIdentity();
mWindowManager.setAppOrientation(r, requestedOrientation);
Configuration config = mWindowManager.updateOrientationFromAppTokens(
@@ -4246,12 +4247,12 @@
if (index < 0) {
return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
}
- HistoryRecord r = (HistoryRecord)mHistory.get(index);
+ ActivityRecord r = (ActivityRecord)mHistory.get(index);
return mWindowManager.getAppOrientation(r);
}
}
- private final void stopActivityLocked(HistoryRecord r) {
+ private final void stopActivityLocked(ActivityRecord r) {
if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
|| (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
@@ -4302,12 +4303,12 @@
if (index < 0) {
return false;
}
- HistoryRecord r = (HistoryRecord)mHistory.get(index);
+ ActivityRecord r = (ActivityRecord)mHistory.get(index);
// Is this the last activity left?
boolean lastActivity = true;
for (int i=mHistory.size()-1; i>=0; i--) {
- HistoryRecord p = (HistoryRecord)mHistory.get(i);
+ ActivityRecord p = (ActivityRecord)mHistory.get(i);
if (!p.finishing && p != r) {
lastActivity = false;
break;
@@ -4330,7 +4331,7 @@
* @return Returns true if this activity has been removed from the history
* list, or false if it is still in the list and will be removed later.
*/
- private final boolean finishActivityLocked(HistoryRecord r, int index,
+ private final boolean finishActivityLocked(ActivityRecord r, int index,
int resultCode, Intent resultData, String reason) {
if (r.finishing) {
Slog.w(TAG, "Duplicate finish request for " + r);
@@ -4343,7 +4344,7 @@
r.task.taskId, r.shortComponentName, reason);
r.task.numActivities--;
if (index < (mHistory.size()-1)) {
- HistoryRecord next = (HistoryRecord)mHistory.get(index+1);
+ ActivityRecord next = (ActivityRecord)mHistory.get(index+1);
if (next.task == r.task) {
if (r.frontOfTask) {
// The next activity is now the front of the task.
@@ -4364,7 +4365,7 @@
}
// send the result
- HistoryRecord resultTo = r.resultTo;
+ ActivityRecord resultTo = r.resultTo;
if (resultTo != null) {
if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
+ " who=" + r.resultWho + " req=" + r.requestCode
@@ -4396,7 +4397,7 @@
if (mResumedActivity == r) {
boolean endTask = index <= 0
- || ((HistoryRecord)mHistory.get(index-1)).task != r.task;
+ || ((ActivityRecord)mHistory.get(index-1)).task != r.task;
if (DEBUG_TRANSITION) Slog.v(TAG,
"Prepare close transition: finishing " + r);
mWindowManager.prepareAppTransition(endTask
@@ -4429,7 +4430,7 @@
private static final int FINISH_AFTER_PAUSE = 1;
private static final int FINISH_AFTER_VISIBLE = 2;
- private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
+ private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
int mode) {
final int index = indexOfTokenLocked(r);
if (index < 0) {
@@ -4439,7 +4440,7 @@
return finishCurrentActivityLocked(r, index, mode);
}
- private final HistoryRecord finishCurrentActivityLocked(HistoryRecord r,
+ private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
int index, int mode) {
// First things first: if this activity is currently visible,
// and the resumed activity is not yet visible, then hold off on
@@ -4504,7 +4505,7 @@
synchronized(this) {
if (mController != null) {
// Find the first activity that is not finishing.
- HistoryRecord next = topRunningActivityLocked(token, 0);
+ ActivityRecord next = topRunningActivityLocked(token, 0);
if (next != null) {
// ask watcher if this is allowed
boolean resumeOK = true;
@@ -4543,10 +4544,10 @@
return;
}
- ArrayList<HistoryRecord> activities = new ArrayList<HistoryRecord>(
+ ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
mHeavyWeightProcess.activities);
for (int i=0; i<activities.size(); i++) {
- HistoryRecord r = activities.get(i);
+ ActivityRecord r = activities.get(i);
if (!r.finishing) {
int index = indexOfTokenLocked(r);
if (index >= 0) {
@@ -4561,7 +4562,61 @@
}
}
- void sendActivityResultLocked(int callingUid, HistoryRecord r,
+ public void crashApplication(int uid, int initialPid, String packageName,
+ String message) {
+ if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
+ != PackageManager.PERMISSION_GRANTED) {
+ String msg = "Permission Denial: crashApplication() from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid()
+ + " requires " + android.Manifest.permission.FORCE_STOP_PACKAGES;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+
+ synchronized(this) {
+ ProcessRecord proc = null;
+
+ // Figure out which process to kill. We don't trust that initialPid
+ // still has any relation to current pids, so must scan through the
+ // list.
+ synchronized (mPidsSelfLocked) {
+ for (int i=0; i<mPidsSelfLocked.size(); i++) {
+ ProcessRecord p = mPidsSelfLocked.valueAt(i);
+ if (p.info.uid != uid) {
+ continue;
+ }
+ if (p.pid == initialPid) {
+ proc = p;
+ break;
+ }
+ for (String str : p.pkgList) {
+ if (str.equals(packageName)) {
+ proc = p;
+ }
+ }
+ }
+ }
+
+ if (proc == null) {
+ Log.w(TAG, "crashApplication: nothing for uid=" + uid
+ + " initialPid=" + initialPid
+ + " packageName=" + packageName);
+ return;
+ }
+
+ if (proc.thread != null) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ proc.thread.scheduleCrash(message);
+ } catch (RemoteException e) {
+ }
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
+ void sendActivityResultLocked(int callingUid, ActivityRecord r,
String resultWho, int requestCode, int resultCode, Intent data) {
if (callingUid > 0) {
@@ -4594,13 +4649,13 @@
if (index < 0) {
return;
}
- HistoryRecord self = (HistoryRecord)mHistory.get(index);
+ ActivityRecord self = (ActivityRecord)mHistory.get(index);
final long origId = Binder.clearCallingIdentity();
int i;
for (i=mHistory.size()-1; i>=0; i--) {
- HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
if (r.resultTo == self && r.requestCode == requestCode) {
if ((r.resultWho == null && resultWho == null) ||
(r.resultWho != null && r.resultWho.equals(resultWho))) {
@@ -4618,7 +4673,7 @@
synchronized(this) {
int i;
for (i=mHistory.size()-1; i>=0; i--) {
- HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
if (r == token) {
return true;
}
@@ -4637,7 +4692,7 @@
if (index < 0) {
return;
}
- HistoryRecord self = (HistoryRecord)mHistory.get(index);
+ ActivityRecord self = (ActivityRecord)mHistory.get(index);
final long origId = Binder.clearCallingIdentity();
@@ -4654,7 +4709,7 @@
/**
* Perform clean-up of service connections in an activity record.
*/
- private final void cleanUpActivityServicesLocked(HistoryRecord r) {
+ private final void cleanUpActivityServicesLocked(ActivityRecord r) {
// Throw away any services that have been bound by this activity.
if (r.connections != null) {
Iterator<ConnectionRecord> it = r.connections.iterator();
@@ -4673,7 +4728,7 @@
* processing going away, in which case there is no remaining client-side
* state to destroy so only the cleanup here is needed.
*/
- private final void cleanUpActivityLocked(HistoryRecord r, boolean cleanServices) {
+ private final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices) {
if (mResumedActivity == r) {
mResumedActivity = null;
}
@@ -4717,7 +4772,7 @@
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
}
- private final void removeActivityFromHistoryLocked(HistoryRecord r) {
+ private final void removeActivityFromHistoryLocked(ActivityRecord r) {
if (r.state != ActivityState.DESTROYED) {
mHistory.remove(r);
r.inHistory = false;
@@ -4737,7 +4792,7 @@
* a configuration switch where we destroy the current client-side object
* but then create a new client-side object for this same HistoryRecord.
*/
- private final boolean destroyActivityLocked(HistoryRecord r,
+ private final boolean destroyActivityLocked(ActivityRecord r,
boolean removeFromApp) {
if (DEBUG_SWITCH) Slog.v(
TAG, "Removing activity: token=" + r
@@ -4827,7 +4882,7 @@
+ " with " + i + " entries");
while (i > 0) {
i--;
- HistoryRecord r = (HistoryRecord)list.get(i);
+ ActivityRecord r = (ActivityRecord)list.get(i);
if (localLOGV) Slog.v(
TAG, "Record #" + i + " " + r + ": app=" + r.app);
if (r.app == app) {
@@ -4873,7 +4928,7 @@
TAG, "Removing app " + app + " from history with " + i + " entries");
while (i > 0) {
i--;
- HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
if (localLOGV) Slog.v(
TAG, "Record #" + i + " " + r + ": app=" + r.app);
if (r.app == app) {
@@ -5078,8 +5133,8 @@
return tracesFile;
}
- final void appNotResponding(ProcessRecord app, HistoryRecord activity,
- HistoryRecord parent, final String annotation) {
+ final void appNotResponding(ProcessRecord app, ActivityRecord activity,
+ ActivityRecord parent, final String annotation) {
ArrayList<Integer> pids = new ArrayList<Integer>(20);
synchronized (this) {
@@ -5231,7 +5286,7 @@
if (index < 0) {
return;
}
- HistoryRecord r = (HistoryRecord)mHistory.get(index);
+ ActivityRecord r = (ActivityRecord)mHistory.get(index);
ProcessRecord app = r.app;
if (localLOGV) Slog.v(
@@ -5283,7 +5338,7 @@
int pid = Binder.getCallingPid();
long callingId = Binder.clearCallingIdentity();
try {
- IPackageManager pm = ActivityThread.getPackageManager();
+ IPackageManager pm = AppGlobals.getPackageManager();
int pkgUid = -1;
synchronized(this) {
try {
@@ -5340,7 +5395,7 @@
long callingId = Binder.clearCallingIdentity();
try {
- IPackageManager pm = ActivityThread.getPackageManager();
+ IPackageManager pm = AppGlobals.getPackageManager();
int pkgUid = -1;
synchronized(this) {
try {
@@ -5372,7 +5427,7 @@
long callingId = Binder.clearCallingIdentity();
try {
- IPackageManager pm = ActivityThread.getPackageManager();
+ IPackageManager pm = AppGlobals.getPackageManager();
int pkgUid = -1;
synchronized(this) {
try {
@@ -5443,7 +5498,7 @@
mWindowManager.closeSystemDialogs(reason);
for (i=mHistory.size()-1; i>=0; i--) {
- HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
finishActivityLocked(r, i,
Activity.RESULT_CANCELED, null, "close-sys");
@@ -5546,7 +5601,7 @@
if (uid < 0) {
try {
- uid = ActivityThread.getPackageManager().getPackageUid(name);
+ uid = AppGlobals.getPackageManager().getPackageUid(name);
} catch (RemoteException e) {
}
}
@@ -5567,7 +5622,7 @@
callerWillRestart, doit);
for (i=mHistory.size()-1; i>=0; i--) {
- HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
if (r.packageName.equals(name)) {
if (!doit) {
return true;
@@ -5839,7 +5894,7 @@
boolean didSomething = false;
// See if the top visible activity is waiting to run in this process...
- HistoryRecord hr = topRunningActivityLocked(null);
+ ActivityRecord hr = topRunningActivityLocked(null);
if (hr != null && normalMode) {
if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
@@ -5941,18 +5996,18 @@
Binder.restoreCallingIdentity(origId);
}
- final ArrayList<HistoryRecord> processStoppingActivitiesLocked(
+ final ArrayList<ActivityRecord> processStoppingActivitiesLocked(
boolean remove) {
int N = mStoppingActivities.size();
if (N <= 0) return null;
- ArrayList<HistoryRecord> stops = null;
+ ArrayList<ActivityRecord> stops = null;
final boolean nowVisible = mResumedActivity != null
&& mResumedActivity.nowVisible
&& !mResumedActivity.waitingVisible;
for (int i=0; i<N; i++) {
- HistoryRecord s = mStoppingActivities.get(i);
+ ActivityRecord s = mStoppingActivities.get(i);
if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
+ nowVisible + " waitingVisible=" + s.waitingVisible
+ " finishing=" + s.finishing);
@@ -5972,7 +6027,7 @@
if (!s.waitingVisible && remove) {
if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
if (stops == null) {
- stops = new ArrayList<HistoryRecord>();
+ stops = new ArrayList<ActivityRecord>();
}
stops.add(s);
mStoppingActivities.remove(i);
@@ -5994,9 +6049,9 @@
Configuration config) {
if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
- ArrayList<HistoryRecord> stops = null;
- ArrayList<HistoryRecord> finishes = null;
- ArrayList<HistoryRecord> thumbnails = null;
+ ArrayList<ActivityRecord> stops = null;
+ ArrayList<ActivityRecord> finishes = null;
+ ArrayList<ActivityRecord> thumbnails = null;
int NS = 0;
int NF = 0;
int NT = 0;
@@ -6012,7 +6067,7 @@
// Get the activity record.
int index = indexOfTokenLocked(token);
if (index >= 0) {
- HistoryRecord r = (HistoryRecord)mHistory.get(index);
+ ActivityRecord r = (ActivityRecord)mHistory.get(index);
if (fromTimeout) {
reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
@@ -6061,11 +6116,11 @@
stops = processStoppingActivitiesLocked(true);
NS = stops != null ? stops.size() : 0;
if ((NF=mFinishingActivities.size()) > 0) {
- finishes = new ArrayList<HistoryRecord>(mFinishingActivities);
+ finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
mFinishingActivities.clear();
}
if ((NT=mCancelledThumbnails.size()) > 0) {
- thumbnails = new ArrayList<HistoryRecord>(mCancelledThumbnails);
+ thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
mCancelledThumbnails.clear();
}
@@ -6088,7 +6143,7 @@
// Stop any activities that are scheduled to do so but have been
// waiting for the next one to start.
for (i=0; i<NS; i++) {
- HistoryRecord r = (HistoryRecord)stops.get(i);
+ ActivityRecord r = (ActivityRecord)stops.get(i);
synchronized (this) {
if (r.finishing) {
finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
@@ -6101,7 +6156,7 @@
// Finish any activities that are scheduled to do so but have been
// waiting for the next one to start.
for (i=0; i<NF; i++) {
- HistoryRecord r = (HistoryRecord)finishes.get(i);
+ ActivityRecord r = (ActivityRecord)finishes.get(i);
synchronized (this) {
destroyActivityLocked(r, true);
}
@@ -6109,7 +6164,7 @@
// Report back to any thumbnail receivers.
for (i=0; i<NT; i++) {
- HistoryRecord r = (HistoryRecord)thumbnails.get(i);
+ ActivityRecord r = (ActivityRecord)thumbnails.get(i);
sendPendingThumbnail(r, null, null, null, true);
}
@@ -6203,12 +6258,12 @@
TAG, "Activity paused: token=" + token + ", icicle=" + icicle
+ ", timeout=" + timeout);
- HistoryRecord r = null;
+ ActivityRecord r = null;
synchronized (this) {
int index = indexOfTokenLocked(token);
if (index >= 0) {
- r = (HistoryRecord)mHistory.get(index);
+ r = (ActivityRecord)mHistory.get(index);
if (!timeout) {
r.icicle = icicle;
r.haveState = true;
@@ -6232,14 +6287,14 @@
if (localLOGV) Slog.v(
TAG, "Activity stopped: token=" + token);
- HistoryRecord r = null;
+ ActivityRecord r = null;
final long origId = Binder.clearCallingIdentity();
synchronized (this) {
int index = indexOfTokenLocked(token);
if (index >= 0) {
- r = (HistoryRecord)mHistory.get(index);
+ r = (ActivityRecord)mHistory.get(index);
r.thumbnail = thumbnail;
r.description = description;
r.stopped = true;
@@ -6269,7 +6324,7 @@
int index = indexOfTokenLocked(token);
if (index >= 0) {
- HistoryRecord r = (HistoryRecord)mHistory.get(index);
+ ActivityRecord r = (ActivityRecord)mHistory.get(index);
if (r.state == ActivityState.DESTROYING) {
final long origId = Binder.clearCallingIdentity();
removeActivityFromHistoryLocked(r);
@@ -6281,22 +6336,22 @@
public String getCallingPackage(IBinder token) {
synchronized (this) {
- HistoryRecord r = getCallingRecordLocked(token);
+ ActivityRecord r = getCallingRecordLocked(token);
return r != null && r.app != null ? r.info.packageName : null;
}
}
public ComponentName getCallingActivity(IBinder token) {
synchronized (this) {
- HistoryRecord r = getCallingRecordLocked(token);
+ ActivityRecord r = getCallingRecordLocked(token);
return r != null ? r.intent.getComponent() : null;
}
}
- private HistoryRecord getCallingRecordLocked(IBinder token) {
+ private ActivityRecord getCallingRecordLocked(IBinder token) {
int index = indexOfTokenLocked(token);
if (index >= 0) {
- HistoryRecord r = (HistoryRecord)mHistory.get(index);
+ ActivityRecord r = (ActivityRecord)mHistory.get(index);
if (r != null) {
return r.resultTo;
}
@@ -6308,7 +6363,7 @@
synchronized(this) {
int index = indexOfTokenLocked(token);
if (index >= 0) {
- HistoryRecord r = (HistoryRecord)mHistory.get(index);
+ ActivityRecord r = (ActivityRecord)mHistory.get(index);
return r.intent.getComponent();
}
return null;
@@ -6319,7 +6374,7 @@
synchronized(this) {
int index = indexOfTokenLocked(token);
if (index >= 0) {
- HistoryRecord r = (HistoryRecord)mHistory.get(index);
+ ActivityRecord r = (ActivityRecord)mHistory.get(index);
return r.packageName;
}
return null;
@@ -6346,7 +6401,7 @@
try {
if (callingUid != 0 && callingUid != Process.SYSTEM_UID &&
Process.supportsProcesses()) {
- int uid = ActivityThread.getPackageManager()
+ int uid = AppGlobals.getPackageManager()
.getPackageUid(packageName);
if (uid != Binder.getCallingUid()) {
String msg = "Permission Denial: getIntentSender() from pid="
@@ -6371,13 +6426,13 @@
IIntentSender getIntentSenderLocked(int type,
String packageName, int callingUid, IBinder token, String resultWho,
int requestCode, Intent intent, String resolvedType, int flags) {
- HistoryRecord activity = null;
+ ActivityRecord activity = null;
if (type == INTENT_SENDER_ACTIVITY_RESULT) {
int index = indexOfTokenLocked(token);
if (index < 0) {
return null;
}
- activity = (HistoryRecord)mHistory.get(index);
+ activity = (ActivityRecord)mHistory.get(index);
if (activity.finishing) {
return null;
}
@@ -6427,7 +6482,7 @@
synchronized(this) {
PendingIntentRecord rec = (PendingIntentRecord)sender;
try {
- int uid = ActivityThread.getPackageManager()
+ int uid = AppGlobals.getPackageManager()
.getPackageUid(rec.key.packageName);
if (uid != Binder.getCallingUid()) {
String msg = "Permission Denial: cancelIntentSender() from pid="
@@ -6586,7 +6641,7 @@
return PackageManager.PERMISSION_GRANTED;
}
try {
- return ActivityThread.getPackageManager()
+ return AppGlobals.getPackageManager()
.checkUidPermission(permission, uid);
} catch (RemoteException e) {
// Should never happen, but if it does... deny!
@@ -6695,7 +6750,7 @@
}
private void grantUriPermissionLocked(int callingUid,
- String targetPkg, Uri uri, int modeFlags, HistoryRecord activity) {
+ String targetPkg, Uri uri, int modeFlags, ActivityRecord activity) {
modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
if (modeFlags == 0) {
@@ -6705,7 +6760,7 @@
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
"Requested grant " + targetPkg + " permission to " + uri);
- final IPackageManager pm = ActivityThread.getPackageManager();
+ final IPackageManager pm = AppGlobals.getPackageManager();
// If this is not a content: uri, we can't do anything with it.
if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
@@ -6824,7 +6879,7 @@
}
private void grantUriPermissionFromIntentLocked(int callingUid,
- String targetPkg, Intent intent, HistoryRecord activity) {
+ String targetPkg, Intent intent, ActivityRecord activity) {
if (intent == null) {
return;
}
@@ -6875,7 +6930,7 @@
}
}
- private void removeActivityUriPermissionsLocked(HistoryRecord activity) {
+ private void removeActivityUriPermissionsLocked(ActivityRecord activity) {
if (activity.readUriPermissions != null) {
for (UriPermission perm : activity.readUriPermissions) {
perm.readActivities.remove(activity);
@@ -6909,7 +6964,7 @@
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
"Revoking all granted permissions to " + uri);
- final IPackageManager pm = ActivityThread.getPackageManager();
+ final IPackageManager pm = AppGlobals.getPackageManager();
final String authority = uri.getAuthority();
ProviderInfo pi = null;
@@ -7003,7 +7058,7 @@
return;
}
- final IPackageManager pm = ActivityThread.getPackageManager();
+ final IPackageManager pm = AppGlobals.getPackageManager();
final String authority = uri.getAuthority();
ProviderInfo pi = null;
@@ -7057,7 +7112,7 @@
PendingThumbnailsRecord pending = null;
IApplicationThread topThumbnail = null;
- HistoryRecord topRecord = null;
+ ActivityRecord topRecord = null;
synchronized(this) {
if (localLOGV) Slog.v(
@@ -7083,17 +7138,17 @@
}
int pos = mHistory.size()-1;
- HistoryRecord next =
- pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
- HistoryRecord top = null;
+ ActivityRecord next =
+ pos >= 0 ? (ActivityRecord)mHistory.get(pos) : null;
+ ActivityRecord top = null;
CharSequence topDescription = null;
TaskRecord curTask = null;
int numActivities = 0;
int numRunning = 0;
while (pos >= 0 && maxNum > 0) {
- final HistoryRecord r = next;
+ final ActivityRecord r = next;
pos--;
- next = pos >= 0 ? (HistoryRecord)mHistory.get(pos) : null;
+ next = pos >= 0 ? (ActivityRecord)mHistory.get(pos) : null;
// Initialize state for next task if needed.
if (top == null ||
@@ -7195,7 +7250,7 @@
enforceCallingPermission(android.Manifest.permission.GET_TASKS,
"getRecentTasks()");
- IPackageManager pm = ActivityThread.getPackageManager();
+ IPackageManager pm = AppGlobals.getPackageManager();
final int N = mRecentTasks.size();
ArrayList<ActivityManager.RecentTaskInfo> res
@@ -7242,12 +7297,12 @@
private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
int j;
- TaskRecord startTask = ((HistoryRecord)mHistory.get(startIndex)).task;
+ TaskRecord startTask = ((ActivityRecord)mHistory.get(startIndex)).task;
TaskRecord jt = startTask;
// First look backwards
for (j=startIndex-1; j>=0; j--) {
- HistoryRecord r = (HistoryRecord)mHistory.get(j);
+ ActivityRecord r = (ActivityRecord)mHistory.get(j);
if (r.task != jt) {
jt = r.task;
if (affinity.equals(jt.affinity)) {
@@ -7260,7 +7315,7 @@
final int N = mHistory.size();
jt = startTask;
for (j=startIndex+1; j<N; j++) {
- HistoryRecord r = (HistoryRecord)mHistory.get(j);
+ ActivityRecord r = (ActivityRecord)mHistory.get(j);
if (r.task != jt) {
if (affinity.equals(jt.affinity)) {
return j;
@@ -7270,7 +7325,7 @@
}
// Might it be at the top?
- if (affinity.equals(((HistoryRecord)mHistory.get(N-1)).task.affinity)) {
+ if (affinity.equals(((ActivityRecord)mHistory.get(N-1)).task.affinity)) {
return N-1;
}
@@ -7281,8 +7336,8 @@
* Perform a reset of the given task, if needed as part of launching it.
* Returns the new HistoryRecord at the top of the task.
*/
- private final HistoryRecord resetTaskIfNeededLocked(HistoryRecord taskTop,
- HistoryRecord newActivity) {
+ private final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
+ ActivityRecord newActivity) {
boolean forceReset = (newActivity.info.flags
&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
if (taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
@@ -7297,13 +7352,13 @@
// We are going to move through the history list so that we can look
// at each activity 'target' with 'below' either the interesting
// activity immediately below it in the stack or null.
- HistoryRecord target = null;
+ ActivityRecord target = null;
int targetI = 0;
int taskTopI = -1;
int replyChainEnd = -1;
int lastReparentPos = -1;
for (int i=mHistory.size()-1; i>=-1; i--) {
- HistoryRecord below = i >= 0 ? (HistoryRecord)mHistory.get(i) : null;
+ ActivityRecord below = i >= 0 ? (ActivityRecord)mHistory.get(i) : null;
if (below != null && below.finishing) {
continue;
@@ -7357,7 +7412,7 @@
// bottom of the activity stack. This also keeps it
// correctly ordered with any activities we previously
// moved.
- HistoryRecord p = (HistoryRecord)mHistory.get(0);
+ ActivityRecord p = (ActivityRecord)mHistory.get(0);
if (target.taskAffinity != null
&& target.taskAffinity.equals(p.task.affinity)) {
// If the activity currently at the bottom has the
@@ -7383,7 +7438,7 @@
}
int dstPos = 0;
for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
- p = (HistoryRecord)mHistory.get(srcPos);
+ p = (ActivityRecord)mHistory.get(srcPos);
if (p.finishing) {
continue;
}
@@ -7422,7 +7477,7 @@
// like these are all in the reply chain.
replyChainEnd = targetI+1;
while (replyChainEnd < mHistory.size() &&
- ((HistoryRecord)mHistory.get(
+ ((ActivityRecord)mHistory.get(
replyChainEnd)).task == task) {
replyChainEnd++;
}
@@ -7430,9 +7485,9 @@
} else if (replyChainEnd < 0) {
replyChainEnd = targetI;
}
- HistoryRecord p = null;
+ ActivityRecord p = null;
for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
- p = (HistoryRecord)mHistory.get(srcPos);
+ p = (ActivityRecord)mHistory.get(srcPos);
if (p.finishing) {
continue;
}
@@ -7490,9 +7545,9 @@
if (replyChainEnd < 0) {
replyChainEnd = targetI;
}
- HistoryRecord p = null;
+ ActivityRecord p = null;
for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
- p = (HistoryRecord)mHistory.get(srcPos);
+ p = (ActivityRecord)mHistory.get(srcPos);
if (p.finishing) {
continue;
}
@@ -7510,7 +7565,7 @@
replyChainEnd = targetI;
}
for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
- HistoryRecord p = (HistoryRecord)mHistory.get(srcPos);
+ ActivityRecord p = (ActivityRecord)mHistory.get(srcPos);
if (p.finishing) {
continue;
}
@@ -7541,7 +7596,7 @@
// below so it remains singleTop.
if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
for (int j=lastReparentPos-1; j>=0; j--) {
- HistoryRecord p = (HistoryRecord)mHistory.get(j);
+ ActivityRecord p = (ActivityRecord)mHistory.get(j);
if (p.finishing) {
continue;
}
@@ -7587,7 +7642,7 @@
}
}
for (int i=mHistory.size()-1; i>=0; i--) {
- HistoryRecord hr = (HistoryRecord)mHistory.get(i);
+ ActivityRecord hr = (ActivityRecord)mHistory.get(i);
if (hr.task.taskId == task) {
moveTaskToFrontLocked(hr.task, null);
return;
@@ -7599,13 +7654,13 @@
}
}
- private final void moveTaskToFrontLocked(TaskRecord tr, HistoryRecord reason) {
+ private final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason) {
if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
final int task = tr.taskId;
int top = mHistory.size()-1;
- if (top < 0 || ((HistoryRecord)mHistory.get(top)).task.taskId == task) {
+ if (top < 0 || ((ActivityRecord)mHistory.get(top)).task.taskId == task) {
// nothing to do!
return;
}
@@ -7620,7 +7675,7 @@
// Shift all activities with this task up to the top
// of the stack, keeping them in the same internal order.
while (pos >= 0) {
- HistoryRecord r = (HistoryRecord)mHistory.get(pos);
+ ActivityRecord r = (ActivityRecord)mHistory.get(pos);
if (localLOGV) Slog.v(
TAG, "At " + pos + " ckp " + r.task + ": " + r);
boolean first = true;
@@ -7643,7 +7698,7 @@
if (reason != null &&
(reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
- HistoryRecord r = topRunningActivityLocked(null);
+ ActivityRecord r = topRunningActivityLocked(null);
if (r != null) {
mNoAnimActivities.add(r);
}
@@ -7713,14 +7768,14 @@
* @param task The taskId to collect and move to the bottom.
* @return Returns true if the move completed, false if not.
*/
- private final boolean moveTaskToBackLocked(int task, HistoryRecord reason) {
+ private final boolean moveTaskToBackLocked(int task, ActivityRecord reason) {
Slog.i(TAG, "moveTaskToBack: " + task);
// If we have a watcher, preflight the move before committing to it. First check
// for *other* available tasks, but if none are available, then try again allowing the
// current task to be selected.
if (mController != null) {
- HistoryRecord next = topRunningActivityLocked(null, task);
+ ActivityRecord next = topRunningActivityLocked(null, task);
if (next == null) {
next = topRunningActivityLocked(null, 0);
}
@@ -7750,7 +7805,7 @@
// Shift all activities with this task down to the bottom
// of the stack, keeping them in the same internal order.
while (pos < N) {
- HistoryRecord r = (HistoryRecord)mHistory.get(pos);
+ ActivityRecord r = (ActivityRecord)mHistory.get(pos);
if (localLOGV) Slog.v(
TAG, "At " + pos + " ckp " + r.task + ": " + r);
if (r.task.taskId == task) {
@@ -7766,7 +7821,7 @@
if (reason != null &&
(reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
mWindowManager.prepareAppTransition(WindowManagerPolicy.TRANSIT_NONE);
- HistoryRecord r = topRunningActivityLocked(null);
+ ActivityRecord r = topRunningActivityLocked(null);
if (r != null) {
mNoAnimActivities.add(r);
}
@@ -7811,7 +7866,7 @@
final int N = mHistory.size();
TaskRecord lastTask = null;
for (int i=0; i<N; i++) {
- HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
if (r == token) {
if (!onlyRoot || lastTask != r.task) {
return r.task.taskId;
@@ -7828,7 +7883,7 @@
* Returns the top activity in any existing task matching the given
* Intent. Returns null if no such task is found.
*/
- private HistoryRecord findTaskLocked(Intent intent, ActivityInfo info) {
+ private ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
ComponentName cls = intent.getComponent();
if (info.targetActivity != null) {
cls = new ComponentName(info.packageName, info.targetActivity);
@@ -7838,7 +7893,7 @@
final int N = mHistory.size();
for (int i=(N-1); i>=0; i--) {
- HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
if (!r.finishing && r.task != cp
&& r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
cp = r.task;
@@ -7874,7 +7929,7 @@
* is the same as the given activity. Returns null if no such activity
* is found.
*/
- private HistoryRecord findActivityLocked(Intent intent, ActivityInfo info) {
+ private ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
ComponentName cls = intent.getComponent();
if (info.targetActivity != null) {
cls = new ComponentName(info.packageName, info.targetActivity);
@@ -7882,7 +7937,7 @@
final int N = mHistory.size();
for (int i=(N-1); i>=0; i--) {
- HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
if (!r.finishing) {
if (r.intent.getComponent().equals(cls)) {
//Slog.i(TAG, "Found matching class!");
@@ -7903,7 +7958,7 @@
int N = mHistory.size();
TaskRecord lastTask = null;
for (int i=0; i<N; i++) {
- HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
if (r.realActivity.equals(className)
&& r != token && lastTask != r.task) {
if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
@@ -7931,7 +7986,7 @@
Binder.restoreCallingIdentity(origId);
}
- final void sendPendingThumbnail(HistoryRecord r, IBinder token,
+ final void sendPendingThumbnail(ActivityRecord r, IBinder token,
Bitmap thumbnail, CharSequence description, boolean always) {
TaskRecord task = null;
ArrayList receivers = null;
@@ -7944,7 +7999,7 @@
if (index < 0) {
return;
}
- r = (HistoryRecord)mHistory.get(index);
+ r = (ActivityRecord)mHistory.get(index);
}
if (thumbnail == null) {
thumbnail = r.thumbnail;
@@ -8005,7 +8060,7 @@
private final List generateApplicationProvidersLocked(ProcessRecord app) {
List providers = null;
try {
- providers = ActivityThread.getPackageManager().
+ providers = AppGlobals.getPackageManager().
queryContentProviders(app.processName, app.info.uid,
STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
} catch (RemoteException ex) {
@@ -8147,7 +8202,7 @@
} else {
try {
- cpi = ActivityThread.getPackageManager().
+ cpi = AppGlobals.getPackageManager().
resolveContentProvider(name,
STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);
} catch (RemoteException ex) {
@@ -8176,7 +8231,7 @@
if (firstClass) {
try {
ApplicationInfo ai =
- ActivityThread.getPackageManager().
+ AppGlobals.getPackageManager().
getApplicationInfo(
cpi.applicationInfo.packageName,
STOCK_PM_FLAGS);
@@ -8481,7 +8536,7 @@
TAG, "Performing unhandledBack(): stack size = " + count);
if (count > 1) {
final long origId = Binder.clearCallingIdentity();
- finishActivityLocked((HistoryRecord)mHistory.get(count-1),
+ finishActivityLocked((ActivityRecord)mHistory.get(count-1),
count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
Binder.restoreCallingIdentity(origId);
}
@@ -8731,7 +8786,7 @@
if (index < 0) {
throw new IllegalArgumentException();
}
- HistoryRecord r = (HistoryRecord)mHistory.get(index);
+ ActivityRecord r = (ActivityRecord)mHistory.get(index);
r.immersive = immersive;
}
}
@@ -8742,14 +8797,14 @@
if (index < 0) {
throw new IllegalArgumentException();
}
- HistoryRecord r = (HistoryRecord)mHistory.get(index);
+ ActivityRecord r = (ActivityRecord)mHistory.get(index);
return r.immersive;
}
}
public boolean isTopActivityImmersive() {
synchronized (this) {
- HistoryRecord r = topRunningActivityLocked(null);
+ ActivityRecord r = topRunningActivityLocked(null);
return (r != null) ? r.immersive : false;
}
}
@@ -8760,7 +8815,7 @@
// and started launching other packages.
if (!mSystemReady) {
try {
- ActivityThread.getPackageManager().enterSafeMode();
+ AppGlobals.getPackageManager().enterSafeMode();
} catch (RemoteException e) {
}
@@ -9033,7 +9088,7 @@
Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
List<ResolveInfo> ris = null;
try {
- ris = ActivityThread.getPackageManager().queryIntentReceivers(
+ ris = AppGlobals.getPackageManager().queryIntentReceivers(
intent, null, 0);
} catch (RemoteException e) {
}
@@ -9152,7 +9207,7 @@
synchronized (this) {
if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
try {
- List apps = ActivityThread.getPackageManager().
+ List apps = AppGlobals.getPackageManager().
getPersistentApplications(STOCK_PM_FLAGS);
if (apps != null) {
int N = apps.size();
@@ -9175,7 +9230,7 @@
mBooting = true;
try {
- if (ActivityThread.getPackageManager().hasSystemUidErrors()) {
+ if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
Message msg = Message.obtain();
msg.what = SHOW_UID_ERROR_MSG;
mHandler.sendMessage(msg);
@@ -9272,7 +9327,7 @@
app.info.processName, app.info.uid);
killServicesLocked(app, false);
for (int i=mHistory.size()-1; i>=0; i--) {
- HistoryRecord r = (HistoryRecord)mHistory.get(i);
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
if (r.app == app) {
Slog.w(TAG, " Force finishing activity "
+ r.intent.getComponent().flattenToShortString());
@@ -9294,7 +9349,7 @@
return false;
}
} else {
- HistoryRecord r = topRunningActivityLocked(null);
+ ActivityRecord r = topRunningActivityLocked(null);
if (r.app == app) {
// If the top running activity is from this crashing
// process, then terminate it to avoid getting in a loop.
@@ -9308,7 +9363,7 @@
// re-start our crashing activity once it gets resumed again.
index--;
if (index >= 0) {
- r = (HistoryRecord)mHistory.get(index);
+ r = (ActivityRecord)mHistory.get(index);
if (r.state == ActivityState.RESUMED
|| r.state == ActivityState.PAUSING
|| r.state == ActivityState.PAUSED) {
@@ -9506,7 +9561,7 @@
* @param crashInfo giving an application stack trace, null if absent
*/
public void addErrorToDropBox(String eventType,
- ProcessRecord process, HistoryRecord activity, HistoryRecord parent, String subject,
+ ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
final String report, final File logFile,
final ApplicationErrorReport.CrashInfo crashInfo) {
// NOTE -- this must never acquire the ActivityManagerService lock,
@@ -9536,7 +9591,7 @@
}
if (process != null) {
int flags = process.info.flags;
- IPackageManager pm = ActivityThread.getPackageManager();
+ IPackageManager pm = AppGlobals.getPackageManager();
sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
for (String pkg : process.pkgList) {
sb.append("Package: ").append(pkg);
@@ -9814,6 +9869,9 @@
new ActivityManager.RunningAppProcessInfo(app.processName,
app.pid, app.getPackageList());
currApp.uid = app.info.uid;
+ if (mHeavyWeightProcess == app) {
+ currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HEAVY_WEIGHT;
+ }
int adj = app.curAdj;
if (adj >= EMPTY_APP_ADJ) {
currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
@@ -9837,8 +9895,8 @@
currApp.importanceReasonCode = app.adjTypeCode;
if (app.adjSource instanceof ProcessRecord) {
currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
- } else if (app.adjSource instanceof HistoryRecord) {
- HistoryRecord r = (HistoryRecord)app.adjSource;
+ } else if (app.adjSource instanceof ActivityRecord) {
+ ActivityRecord r = (ActivityRecord)app.adjSource;
if (r.app != null) currApp.importanceReasonPid = r.app.pid;
}
if (app.adjTarget instanceof ComponentName) {
@@ -9868,7 +9926,7 @@
}
}
}
- IPackageManager pm = ActivityThread.getPackageManager();
+ IPackageManager pm = AppGlobals.getPackageManager();
for (String pkg : extList) {
try {
ApplicationInfo info = pm.getApplicationInfo(pkg, 0);
@@ -10555,7 +10613,7 @@
String prefix, String label, boolean complete) {
TaskRecord lastTask = null;
for (int i=list.size()-1; i>=0; i--) {
- HistoryRecord r = (HistoryRecord)list.get(i);
+ ActivityRecord r = (ActivityRecord)list.get(i);
final boolean full = complete || !r.inHistory;
if (lastTask != r.task) {
lastTask = r.task;
@@ -11183,7 +11241,7 @@
if (r == null) {
try {
ResolveInfo rInfo =
- ActivityThread.getPackageManager().resolveService(
+ AppGlobals.getPackageManager().resolveService(
service, resolvedType, 0);
ServiceInfo sInfo =
rInfo != null ? rInfo.serviceInfo : null;
@@ -11240,7 +11298,7 @@
if (r == null) {
try {
ResolveInfo rInfo =
- ActivityThread.getPackageManager().resolveService(
+ AppGlobals.getPackageManager().resolveService(
service, resolvedType, STOCK_PM_FLAGS);
ServiceInfo sInfo =
rInfo != null ? rInfo.serviceInfo : null;
@@ -12011,14 +12069,14 @@
+ ") when binding service " + service);
}
- HistoryRecord activity = null;
+ ActivityRecord activity = null;
if (token != null) {
int aindex = indexOfTokenLocked(token);
if (aindex < 0) {
Slog.w(TAG, "Binding with unknown activity: " + token);
return 0;
}
- activity = (HistoryRecord)mHistory.get(aindex);
+ activity = (ActivityRecord)mHistory.get(aindex);
}
int clientLabel = 0;
@@ -12123,7 +12181,7 @@
}
private void removeConnectionLocked(
- ConnectionRecord c, ProcessRecord skipApp, HistoryRecord skipAct) {
+ ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
IBinder binder = c.conn.asBinder();
AppBindRecord b = c.binding;
ServiceRecord s = b.service;
@@ -12804,7 +12862,7 @@
// Always okay.
} else if (callerApp == null || !callerApp.persistent) {
try {
- if (ActivityThread.getPackageManager().isProtectedBroadcast(
+ if (AppGlobals.getPackageManager().isProtectedBroadcast(
intent.getAction())) {
String msg = "Permission Denial: not allowed to send broadcast "
+ intent.getAction() + " from pid="
@@ -12863,7 +12921,7 @@
try {
if (intent.getComponent() != null) {
// Broadcast is going to one specific receiver class...
- ActivityInfo ai = ActivityThread.getPackageManager().
+ ActivityInfo ai = AppGlobals.getPackageManager().
getReceiverInfo(intent.getComponent(), STOCK_PM_FLAGS);
if (ai != null) {
receivers = new ArrayList();
@@ -12876,7 +12934,7 @@
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
== 0) {
receivers =
- ActivityThread.getPackageManager().queryIntentReceivers(
+ AppGlobals.getPackageManager().queryIntentReceivers(
intent, resolvedType, STOCK_PM_FLAGS);
}
registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false);
@@ -13628,7 +13686,7 @@
if (r.callingUid != Process.SYSTEM_UID &&
r.requiredPermission != null) {
try {
- perm = ActivityThread.getPackageManager().
+ perm = AppGlobals.getPackageManager().
checkPermission(r.requiredPermission,
info.activityInfo.applicationInfo.packageName);
} catch (RemoteException e) {
@@ -13885,7 +13943,7 @@
* configuration.
*/
public boolean updateConfigurationLocked(Configuration values,
- HistoryRecord starting) {
+ ActivityRecord starting) {
int changes = 0;
boolean kept = true;
@@ -13976,7 +14034,7 @@
return kept;
}
- private final boolean relaunchActivityLocked(HistoryRecord r,
+ private final boolean relaunchActivityLocked(ActivityRecord r,
int changes, boolean andResume) {
List<ResultInfo> results = null;
List<Intent> newIntents = null;
@@ -14020,7 +14078,7 @@
* for whatever reason. Ensures the HistoryRecord is updated with the
* correct configuration and all other bookkeeping is handled.
*/
- private final boolean ensureActivityConfigurationLocked(HistoryRecord r,
+ private final boolean ensureActivityConfigurationLocked(ActivityRecord r,
int globalChanges) {
if (mConfigWillChange) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
@@ -14354,7 +14412,7 @@
}
}
}
- HistoryRecord a = cr.activity;
+ ActivityRecord a = cr.activity;
//if (a != null) {
// Slog.i(TAG, "Connection to " + a ": state=" + a.state);
//}
@@ -14655,8 +14713,8 @@
return true;
}
- private final HistoryRecord resumedAppLocked() {
- HistoryRecord resumedActivity = mResumedActivity;
+ private final ActivityRecord resumedAppLocked() {
+ ActivityRecord resumedActivity = mResumedActivity;
if (resumedActivity == null || resumedActivity.app == null) {
resumedActivity = mPausingActivity;
if (resumedActivity == null || resumedActivity.app == null) {
@@ -14667,7 +14725,7 @@
}
private final boolean updateOomAdjLocked(ProcessRecord app) {
- final HistoryRecord TOP_ACT = resumedAppLocked();
+ final ActivityRecord TOP_ACT = resumedAppLocked();
final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
int curAdj = app.curAdj;
final boolean wasHidden = app.curAdj >= HIDDEN_APP_MIN_ADJ
@@ -14690,7 +14748,7 @@
private final boolean updateOomAdjLocked() {
boolean didOomAdj = true;
- final HistoryRecord TOP_ACT = resumedAppLocked();
+ final ActivityRecord TOP_ACT = resumedAppLocked();
final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
if (false) {
@@ -14872,7 +14930,7 @@
if (Config.LOGV) Slog.v(
TAG, "Looking to quit " + app.processName);
for (j=0; j<NUMA && canQuit; j++) {
- HistoryRecord r = app.activities.get(j);
+ ActivityRecord r = app.activities.get(j);
if (Config.LOGV) Slog.v(
TAG, " " + r.intent.getComponent().flattenToShortString()
+ ": frozen=" + r.haveState + ", visible=" + r.visible);
@@ -14882,7 +14940,7 @@
if (canQuit) {
// Finish all of the activities, and then the app itself.
for (j=0; j<NUMA; j++) {
- HistoryRecord r = app.activities.get(j);
+ ActivityRecord r = app.activities.get(j);
if (!r.finishing) {
destroyActivityLocked(r, false);
}
@@ -14924,8 +14982,8 @@
i<mLRUActivities.size()
&& mLRUActivities.size() > curMaxActivities;
i++) {
- final HistoryRecord r
- = (HistoryRecord)mLRUActivities.get(i);
+ final ActivityRecord r
+ = (ActivityRecord)mLRUActivities.get(i);
// We can finish this one if we have its icicle saved and
// it is not persistent.
diff --git a/services/java/com/android/server/am/HistoryRecord.java b/services/java/com/android/server/am/ActivityRecord.java
similarity index 97%
rename from services/java/com/android/server/am/HistoryRecord.java
rename to services/java/com/android/server/am/ActivityRecord.java
index fb5c8aa0..22ac58d 100644
--- a/services/java/com/android/server/am/HistoryRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -42,7 +42,7 @@
/**
* An entry in the history stack, representing an activity.
*/
-class HistoryRecord extends IApplicationToken.Stub {
+class ActivityRecord extends IApplicationToken.Stub {
final ActivityManagerService service; // owner
final ActivityInfo info; // all about me
final int launchedFromUid; // always the uid who started the activity.
@@ -68,7 +68,7 @@
long startTime; // when we starting launching this activity
long cpuTimeAtResume; // the cpu time of host process at the time of resuming activity
Configuration configuration; // configuration activity was last running in
- HistoryRecord resultTo; // who started this entry, so will get our reply
+ ActivityRecord resultTo; // who started this entry, so will get our reply
final String resultWho; // additional identifier for use by resultTo.
final int requestCode; // code given by requester (resultTo)
ArrayList results; // pending ActivityResult objs we have received
@@ -175,10 +175,10 @@
}
}
- HistoryRecord(ActivityManagerService _service, ProcessRecord _caller,
+ ActivityRecord(ActivityManagerService _service, ProcessRecord _caller,
int _launchedFromUid, Intent _intent, String _resolvedType,
ActivityInfo aInfo, Configuration _configuration,
- HistoryRecord _resultTo, String _resultWho, int _reqCode,
+ ActivityRecord _resultTo, String _resultWho, int _reqCode,
boolean _componentSpecified) {
service = _service;
info = aInfo;
@@ -297,7 +297,7 @@
}
}
- void addResultLocked(HistoryRecord from, String resultWho,
+ void addResultLocked(ActivityRecord from, String resultWho,
int requestCode, int resultCode,
Intent resultData) {
ActivityResult r = new ActivityResult(from, resultWho,
@@ -308,7 +308,7 @@
results.add(r);
}
- void removeResultsLocked(HistoryRecord from, String resultWho,
+ void removeResultsLocked(ActivityRecord from, String resultWho,
int requestCode) {
if (results != null) {
for (int i=results.size()-1; i>=0; i--) {
@@ -418,7 +418,7 @@
final int N = service.mWaitingVisibleActivities.size();
if (N > 0) {
for (int i=0; i<N; i++) {
- HistoryRecord r = (HistoryRecord)
+ ActivityRecord r = (ActivityRecord)
service.mWaitingVisibleActivities.get(i);
r.waitingVisible = false;
if (ActivityManagerService.DEBUG_SWITCH) Log.v(
@@ -442,11 +442,11 @@
nowVisible = false;
}
- private HistoryRecord getWaitingHistoryRecordLocked() {
+ private ActivityRecord getWaitingHistoryRecordLocked() {
// First find the real culprit... if we are waiting
// for another app to start, then we have paused dispatching
// for this activity.
- HistoryRecord r = this;
+ ActivityRecord r = this;
if (r.waitingVisible) {
// Hmmm, who might we be waiting for?
r = service.mResumedActivity;
@@ -463,7 +463,7 @@
}
public boolean keyDispatchingTimedOut() {
- HistoryRecord r;
+ ActivityRecord r;
ProcessRecord anrApp = null;
synchronized(service) {
r = getWaitingHistoryRecordLocked();
@@ -501,7 +501,7 @@
/** Returns the key dispatching timeout for this application token. */
public long getKeyDispatchingTimeout() {
synchronized(service) {
- HistoryRecord r = getWaitingHistoryRecordLocked();
+ ActivityRecord r = getWaitingHistoryRecordLocked();
if (r == null || r.app == null
|| r.app.instrumentationClass == null) {
return ActivityManagerService.KEY_DISPATCHING_TIMEOUT;
diff --git a/services/java/com/android/server/am/ActivityResult.java b/services/java/com/android/server/am/ActivityResult.java
index 3cc2725..12eba34 100644
--- a/services/java/com/android/server/am/ActivityResult.java
+++ b/services/java/com/android/server/am/ActivityResult.java
@@ -24,9 +24,9 @@
* Pending result information to send back to an activity.
*/
class ActivityResult extends ResultInfo {
- final HistoryRecord mFrom;
+ final ActivityRecord mFrom;
- public ActivityResult(HistoryRecord from, String resultWho,
+ public ActivityResult(ActivityRecord from, String resultWho,
int requestCode, int resultCode, Intent data) {
super(resultWho, requestCode, resultCode, data);
mFrom = from;
diff --git a/services/java/com/android/server/am/AppNotRespondingDialog.java b/services/java/com/android/server/am/AppNotRespondingDialog.java
index 9702f91..b2737dc 100644
--- a/services/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/java/com/android/server/am/AppNotRespondingDialog.java
@@ -40,7 +40,7 @@
private final ProcessRecord mProc;
public AppNotRespondingDialog(ActivityManagerService service, Context context,
- ProcessRecord app, HistoryRecord activity) {
+ ProcessRecord app, ActivityRecord activity) {
super(context);
mService = service;
diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java
index f613b00..22acda9 100644
--- a/services/java/com/android/server/am/ConnectionRecord.java
+++ b/services/java/com/android/server/am/ConnectionRecord.java
@@ -26,7 +26,7 @@
*/
class ConnectionRecord {
final AppBindRecord binding; // The application/service binding.
- final HistoryRecord activity; // If non-null, the owning activity.
+ final ActivityRecord activity; // If non-null, the owning activity.
final IServiceConnection conn; // The client connection.
final int flags; // Binding options.
final int clientLabel; // String resource labeling this client.
@@ -42,7 +42,7 @@
+ " flags=0x" + Integer.toHexString(flags));
}
- ConnectionRecord(AppBindRecord _binding, HistoryRecord _activity,
+ ConnectionRecord(AppBindRecord _binding, ActivityRecord _activity,
IServiceConnection _conn, int _flags,
int _clientLabel, PendingIntent _clientIntent) {
binding = _binding;
diff --git a/services/java/com/android/server/am/PendingIntentRecord.java b/services/java/com/android/server/am/PendingIntentRecord.java
index 847e91b..e7e9130 100644
--- a/services/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/java/com/android/server/am/PendingIntentRecord.java
@@ -42,7 +42,7 @@
final static class Key {
final int type;
final String packageName;
- final HistoryRecord activity;
+ final ActivityRecord activity;
final String who;
final int requestCode;
final Intent requestIntent;
@@ -52,7 +52,7 @@
private static final int ODD_PRIME_NUMBER = 37;
- Key(int _t, String _p, HistoryRecord _a, String _w,
+ Key(int _t, String _p, ActivityRecord _a, String _w,
int _r, Intent _i, String _it, int _f) {
type = _t;
packageName = _p;
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 9dda1df..18fd9d6 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -86,7 +86,7 @@
Object adjTarget; // Debugging: target component impacting oom_adj.
// contains HistoryRecord objects
- final ArrayList<HistoryRecord> activities = new ArrayList<HistoryRecord>();
+ final ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
// all ServiceRecord running in this process
final HashSet<ServiceRecord> services = new HashSet<ServiceRecord>();
// services that are currently executing code (need to remain foreground).
@@ -248,7 +248,7 @@
public boolean isInterestingToUserLocked() {
final int size = activities.size();
for (int i = 0 ; i < size ; i++) {
- HistoryRecord r = activities.get(i);
+ ActivityRecord r = activities.get(i);
if (r.isInterestingToUserLocked()) {
return true;
}
diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java
index ffa8a2a..81450c5 100644
--- a/services/java/com/android/server/am/UriPermission.java
+++ b/services/java/com/android/server/am/UriPermission.java
@@ -27,8 +27,8 @@
final Uri uri;
int modeFlags = 0;
int globalModeFlags = 0;
- final HashSet<HistoryRecord> readActivities = new HashSet<HistoryRecord>();
- final HashSet<HistoryRecord> writeActivities = new HashSet<HistoryRecord>();
+ final HashSet<ActivityRecord> readActivities = new HashSet<ActivityRecord>();
+ final HashSet<ActivityRecord> writeActivities = new HashSet<ActivityRecord>();
String stringName;
@@ -42,7 +42,7 @@
globalModeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION;
if (readActivities.size() > 0) {
- for (HistoryRecord r : readActivities) {
+ for (ActivityRecord r : readActivities) {
r.readUriPermissions.remove(this);
if (r.readUriPermissions.size() == 0) {
r.readUriPermissions = null;
@@ -55,7 +55,7 @@
globalModeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
if (readActivities.size() > 0) {
- for (HistoryRecord r : readActivities) {
+ for (ActivityRecord r : readActivities) {
r.writeUriPermissions.remove(this);
if (r.writeUriPermissions.size() == 0) {
r.writeUriPermissions = null;
diff --git a/tests/FixVibrateSetting/Android.mk b/tests/FixVibrateSetting/Android.mk
new file mode 100644
index 0000000..2a88e5a
--- /dev/null
+++ b/tests/FixVibrateSetting/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := FixVibrateSetting
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/tests/FixVibrateSetting/AndroidManifest.xml b/tests/FixVibrateSetting/AndroidManifest.xml
new file mode 100644
index 0000000..007d682
--- /dev/null
+++ b/tests/FixVibrateSetting/AndroidManifest.xml
@@ -0,0 +1,14 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.fixvibratesetting">
+ <uses-permission android:name="android.permission.VIBRATE" />
+
+ <application>
+ <activity android:name="FixVibrateSetting" android:label="@string/app_label">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/FixVibrateSetting/res/drawable-hdpi/stat_sys_warning.png b/tests/FixVibrateSetting/res/drawable-hdpi/stat_sys_warning.png
new file mode 100644
index 0000000..37c8853
--- /dev/null
+++ b/tests/FixVibrateSetting/res/drawable-hdpi/stat_sys_warning.png
Binary files differ
diff --git a/tests/FixVibrateSetting/res/drawable-mdpi/stat_sys_warning.png b/tests/FixVibrateSetting/res/drawable-mdpi/stat_sys_warning.png
new file mode 100644
index 0000000..be00f47
--- /dev/null
+++ b/tests/FixVibrateSetting/res/drawable-mdpi/stat_sys_warning.png
Binary files differ
diff --git a/tests/FixVibrateSetting/res/layout/fix_vibrate.xml b/tests/FixVibrateSetting/res/layout/fix_vibrate.xml
new file mode 100644
index 0000000..c505e65
--- /dev/null
+++ b/tests/FixVibrateSetting/res/layout/fix_vibrate.xml
@@ -0,0 +1,46 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ >
+
+ <TextView android:id="@+id/current_setting"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left"
+ android:layout_marginTop="30dp"
+ android:layout_marginBottom="50dp"
+ android:paddingLeft="8dp"
+ android:paddingTop="4dp"
+ android:textSize="20sp"
+ android:textColor="#ffffffff"
+ />
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:orientation="horizontal"
+ >
+ <Button android:id="@+id/fix"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/fix"
+ />
+
+ <Button android:id="@+id/unfix"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/unfix"
+ />
+ </LinearLayout>
+
+ <Button android:id="@+id/test"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:text="@string/test"
+ />
+
+</LinearLayout>
+
diff --git a/tests/FixVibrateSetting/res/values/strings.xml b/tests/FixVibrateSetting/res/values/strings.xml
new file mode 100644
index 0000000..269cef3
--- /dev/null
+++ b/tests/FixVibrateSetting/res/values/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <string name="app_label">Fix Vibrate</string>
+ <string name="title">Fix vibrate setting</string>
+ <string name="current_setting">"Ringer: %1$s\nNotification: %2$s"</string>
+ <string name="fix">Fix the setting</string>
+ <string name="unfix">Break the setting</string>
+ <string name="test">Test the setting</string>
+</resources>
+
diff --git a/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java b/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java
new file mode 100644
index 0000000..947ea78
--- /dev/null
+++ b/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.fixvibratesetting;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.util.Log;
+import android.view.View;
+import android.widget.TextView;
+import android.os.Bundle;
+
+public class FixVibrateSetting extends Activity implements View.OnClickListener
+{
+ AudioManager mAudioManager;
+ NotificationManager mNotificationManager;
+ TextView mCurrentSetting;
+ View mFix;
+ View mUnfix;
+ View mTest;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ setContentView(R.layout.fix_vibrate);
+
+ mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
+ mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
+
+ mCurrentSetting = (TextView)findViewById(R.id.current_setting);
+
+ mFix = findViewById(R.id.fix);
+ mFix.setOnClickListener(this);
+
+ mUnfix = findViewById(R.id.unfix);
+ mUnfix.setOnClickListener(this);
+
+ mTest = findViewById(R.id.test);
+ mTest.setOnClickListener(this);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ update();
+ }
+
+ private String getSettingValue(int vibrateType) {
+ int setting = mAudioManager.getVibrateSetting(vibrateType);
+ switch (setting) {
+ case AudioManager.VIBRATE_SETTING_OFF:
+ return "off";
+ case AudioManager.VIBRATE_SETTING_ON:
+ return "on";
+ case AudioManager.VIBRATE_SETTING_ONLY_SILENT:
+ return "silent-only";
+ default:
+ return "unknown";
+ }
+ }
+
+ public void onClick(View v) {
+ if (v == mFix) {
+ fix();
+ update();
+ } else if (v == mUnfix) {
+ unfix();
+ update();
+ } else if (v == mTest) {
+ test();
+ update();
+ }
+ }
+
+ private void update() {
+ String ringer = getSettingValue(AudioManager.VIBRATE_TYPE_RINGER);
+ String notification = getSettingValue(AudioManager.VIBRATE_TYPE_NOTIFICATION);
+ String text = getString(R.string.current_setting, ringer, notification);
+ mCurrentSetting.setText(text);
+ }
+
+ private void fix() {
+ mAudioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,
+ AudioManager.VIBRATE_SETTING_ON);
+ }
+
+ private void unfix() {
+ mAudioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION,
+ AudioManager.VIBRATE_SETTING_OFF);
+ }
+
+ private void test() {
+ Notification n = new Notification(R.drawable.stat_sys_warning, "Test notification",
+ System.currentTimeMillis());
+ Intent intent = new Intent(this, FixVibrateSetting.class);
+ PendingIntent pending = PendingIntent.getActivity(this, 0, intent, 0);
+ n.setLatestEventInfo(this, "Test notification", "Test notification", pending);
+
+ n.vibrate = new long[] { 0, 700, 500, 1000 };
+ n.flags |= Notification.FLAG_AUTO_CANCEL;
+ mNotificationManager.notify(1, n);
+ }
+}
+
diff --git a/tests/StatusBar/Android.mk b/tests/StatusBar/Android.mk
index 18fcad0..502657f 100644
--- a/tests/StatusBar/Android.mk
+++ b/tests/StatusBar/Android.mk
@@ -8,4 +8,6 @@
LOCAL_PACKAGE_NAME := StatusBarTest
LOCAL_CERTIFICATE := platform
+LOCAL_PROGUARD_ENABLED := disabled
+
include $(BUILD_PACKAGE)
diff --git a/tests/StatusBar/AndroidManifest.xml b/tests/StatusBar/AndroidManifest.xml
index 21fb951..c1ca618 100644
--- a/tests/StatusBar/AndroidManifest.xml
+++ b/tests/StatusBar/AndroidManifest.xml
@@ -35,5 +35,7 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <activity android:name="TestAlertActivity" android:theme="@android:style/Theme.Dialog">
+ </activity>
</application>
</manifest>
diff --git a/tests/StatusBar/res/layout/test_alert.xml b/tests/StatusBar/res/layout/test_alert.xml
new file mode 100644
index 0000000..325146c
--- /dev/null
+++ b/tests/StatusBar/res/layout/test_alert.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:gravity="center_horizontal"
+ android:orientation="vertical"
+ >
+
+ <TextView android:id="@+id/alertTitle"
+ style="?android:attr/textAppearanceLarge"
+ android:padding="5dip"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:gravity="center"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="@android:style/ButtonBar">
+
+ <Button
+ android:id="@+id/snooze"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="3"
+ android:onClick="dismiss"
+ android:text="Snooze" />
+
+ <!-- blank stretchable view -->
+ <View
+ android:layout_width="2dip"
+ android:layout_height="2dip"
+ android:layout_gravity="fill_horizontal"
+ android:layout_weight="1"/>
+
+ <Button
+ android:id="@+id/dismiss"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="3"
+ android:onClick="dismiss"
+ android:text="Dismiss" />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
index cb94e52..8c343b5 100644
--- a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
@@ -23,6 +23,7 @@
import android.view.View;
import android.widget.ListView;
import android.content.Intent;
+import android.app.PendingIntent;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.StatusBarManager;
@@ -35,6 +36,8 @@
import android.widget.RemoteViews;
import android.widget.Toast;
import android.os.PowerManager;
+import android.view.Window;
+import android.view.WindowManager;
public class StatusBarTest extends TestActivity
{
@@ -57,6 +60,53 @@
}
private Test[] mTests = new Test[] {
+ new Test("Hide") {
+ public void run() {
+ Window win = getWindow();
+ WindowManager.LayoutParams winParams = win.getAttributes();
+ winParams.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
+ win.setAttributes(winParams);
+ }
+ },
+ new Test("Show") {
+ public void run() {
+ Window win = getWindow();
+ WindowManager.LayoutParams winParams = win.getAttributes();
+ winParams.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
+ win.setAttributes(winParams);
+ }
+ },
+ new Test("Immersive: Enter") {
+ public void run() {
+ setImmersive(true);
+ }
+ },
+ new Test("Immersive: Exit") {
+ public void run() {
+ setImmersive(false);
+ }
+ },
+ new Test("Priority notification") {
+ public void run() {
+ Notification not = new Notification(StatusBarTest.this,
+ R.drawable.ic_statusbar_missedcall,
+ "tick tick tick",
+ System.currentTimeMillis()-(1000*60*60*24),
+ "(453) 123-2328",
+ "", null
+ );
+ not.flags |= Notification.FLAG_HIGH_PRIORITY;
+ Intent fullScreenIntent = new Intent(StatusBarTest.this, TestAlertActivity.class);
+ int id = (int)System.currentTimeMillis(); // XXX HAX
+ fullScreenIntent.putExtra("id", id);
+ not.fullScreenIntent = PendingIntent.getActivity(
+ StatusBarTest.this,
+ 0,
+ fullScreenIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ mNotificationManager.notify(id, not);
+ }
+ },
new Test("Disable Alerts") {
public void run() {
mStatusBarManager.disable(StatusBarManager.DISABLE_NOTIFICATION_ALERTS);
diff --git a/tests/StatusBar/src/com/android/statusbartest/TestAlertActivity.java b/tests/StatusBar/src/com/android/statusbartest/TestAlertActivity.java
new file mode 100644
index 0000000..f5876d0
--- /dev/null
+++ b/tests/StatusBar/src/com/android/statusbartest/TestAlertActivity.java
@@ -0,0 +1,37 @@
+package com.android.statusbartest;
+
+import android.app.Activity;
+import android.app.NotificationManager;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+
+public class TestAlertActivity extends Activity {
+ int mId;
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ Log.d("StatusBarTest", "TestAlertActivity.onResume");
+ Intent intent = getIntent();
+ mId = intent.getIntExtra("id", -1);
+ Log.d("StatusBarTest", "Remembering notification id=" + mId);
+ setContentView(R.layout.test_alert);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ Log.d("StatusBarTest", "onPause: Canceling notification id=" + mId);
+ NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+ nm.cancel(mId);
+ finish();
+ }
+
+ @SuppressWarnings({"UnusedDeclaration"})
+ public void dismiss(View v) {
+ Log.d("StatusBarTest", "TestAlertActivity.dismiss");
+ finish();
+ }
+}
diff --git a/tests/appwidgets/AppWidgetProviderTest/res/layout/test_appwidget2.xml b/tests/appwidgets/AppWidgetProviderTest/res/layout/test_appwidget2.xml
new file mode 100644
index 0000000..abc6f59
--- /dev/null
+++ b/tests/appwidgets/AppWidgetProviderTest/res/layout/test_appwidget2.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/oh_hai_text"
+ android:layout_width="150dp"
+ android:layout_height="150dp"
+ android:text="@string/appwidget_view_title"
+ android:background="#8fff"
+ android:textColor="#000"
+ android:textStyle="bold"
+/>
+
diff --git a/tests/appwidgets/AppWidgetProviderTest/src/com/android/tests/appwidgetprovider/TestAppWidgetProvider.java b/tests/appwidgets/AppWidgetProviderTest/src/com/android/tests/appwidgetprovider/TestAppWidgetProvider.java
index 418be65..d9c0110 100644
--- a/tests/appwidgets/AppWidgetProviderTest/src/com/android/tests/appwidgetprovider/TestAppWidgetProvider.java
+++ b/tests/appwidgets/AppWidgetProviderTest/src/com/android/tests/appwidgetprovider/TestAppWidgetProvider.java
@@ -41,6 +41,7 @@
Log.d(TAG, "DISABLED");
}
else if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
+ if (true) return;
Log.d(TAG, "UPDATE");
Bundle extras = intent.getExtras();
int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);