Merge "Fix DevicePolicyManager crash when settings password quality (and possibly others)." into jb-mr1-dev
diff --git a/api/current.txt b/api/current.txt
index 9d7bb14..c1d8c9e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3353,6 +3353,7 @@
method public final android.app.FragmentManager getFragmentManager();
method public final int getId();
method public android.app.LoaderManager getLoaderManager();
+ method public final android.app.Fragment getParentFragment();
method public final android.content.res.Resources getResources();
method public final boolean getRetainInstance();
method public final java.lang.String getString(int);
@@ -18383,6 +18384,7 @@
field public static final java.lang.String INTENT_ACTION_MEDIA_SEARCH = "android.intent.action.MEDIA_SEARCH";
field public static final deprecated java.lang.String INTENT_ACTION_MUSIC_PLAYER = "android.intent.action.MUSIC_PLAYER";
field public static final java.lang.String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA";
+ field public static final java.lang.String INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE = "android.media.action.STILL_IMAGE_CAMERA_SECURE";
field public static final java.lang.String INTENT_ACTION_VIDEO_CAMERA = "android.media.action.VIDEO_CAMERA";
field public static final java.lang.String MEDIA_IGNORE_FILENAME = ".nomedia";
field public static final java.lang.String MEDIA_SCANNER_VOLUME = "volume";
diff --git a/cmds/svc/src/com/android/commands/svc/PowerCommand.java b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
index ec3ec3e..58105fa 100644
--- a/cmds/svc/src/com/android/commands/svc/PowerCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
@@ -16,14 +16,12 @@
package com.android.commands.svc;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.IPowerManager;
-import android.os.PowerManager;
-import android.os.ServiceManager;
-import android.os.RemoteException;
-import android.os.BatteryManager;
import android.content.Context;
+import android.os.BatteryManager;
+import android.os.IPowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
public class PowerCommand extends Svc.Command {
public PowerCommand() {
@@ -65,10 +63,12 @@
IPowerManager pm
= IPowerManager.Stub.asInterface(ServiceManager.getService(Context.POWER_SERVICE));
try {
- IBinder lock = new Binder();
- pm.acquireWakeLock(lock, PowerManager.FULL_WAKE_LOCK, "svc power", null);
+ if (val != 0) {
+ // if the request is not to set it to false, wake up the screen so that
+ // it can stay on as requested
+ pm.wakeUp(SystemClock.uptimeMillis());
+ }
pm.setStayOnSetting(val);
- pm.releaseWakeLock(lock, 0);
}
catch (RemoteException e) {
System.err.println("Faild to set setting: " + e);
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 3ff9df5..c5a382d 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -615,7 +615,7 @@
+ " did not call through to super.onViewStateRestored()");
}
}
-
+
final void setIndex(int index, Fragment parent) {
mIndex = index;
if (parent != null) {
@@ -623,8 +623,8 @@
} else {
mWho = "android:fragment:" + mIndex;
}
- }
-
+ }
+
final boolean isInBackStack() {
return mBackStackNesting > 0;
}
@@ -832,6 +832,14 @@
}
/**
+ * Returns the parent Fragment containing this Fragment. If this Fragment
+ * is attached directly to an Activity, returns null.
+ */
+ final public Fragment getParentFragment() {
+ return mParentFragment;
+ }
+
+ /**
* Return true if the fragment is currently added to its activity.
*/
final public boolean isAdded() {
@@ -1180,20 +1188,7 @@
public void onCreate(Bundle savedInstanceState) {
mCalled = true;
}
-
- /**
- * Called immediately after {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}
- * has returned, but before any saved state has been restored in to the view.
- * This gives subclasses a chance to initialize themselves once
- * they know their view hierarchy has been completely created. The fragment's
- * view hierarchy is not however attached to its parent at this point.
- * @param view The View returned by {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}.
- * @param savedInstanceState If non-null, this fragment is being re-constructed
- * from a previous saved state as given here.
- */
- public void onViewCreated(View view, Bundle savedInstanceState) {
- }
-
+
/**
* Called to have the fragment instantiate its user interface view.
* This is optional, and non-graphical fragments can return null (which
@@ -1217,6 +1212,19 @@
Bundle savedInstanceState) {
return null;
}
+
+ /**
+ * Called immediately after {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}
+ * has returned, but before any saved state has been restored in to the view.
+ * This gives subclasses a chance to initialize themselves once
+ * they know their view hierarchy has been completely created. The fragment's
+ * view hierarchy is not however attached to its parent at this point.
+ * @param view The View returned by {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}.
+ * @param savedInstanceState If non-null, this fragment is being re-constructed
+ * from a previous saved state as given here.
+ */
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ }
/**
* Get the root view for the fragment's layout (the one returned by {@link #onCreateView}),
@@ -1237,7 +1245,7 @@
* as this callback tells the fragment when it is fully associated with
* the new activity instance. This is called after {@link #onCreateView}
* and before {@link #onViewStateRestored(Bundle)}.
- *
+ *
* @param savedInstanceState If the fragment is being re-created from
* a previous saved state, this is the state.
*/
@@ -1252,7 +1260,7 @@
* whether check box widgets are currently checked. This is called
* after {@link #onActivityCreated(Bundle)} and before
* {@link #onStart()}.
- *
+ *
* @param savedInstanceState If the fragment is being re-created from
* a previous saved state, this is the state.
*/
@@ -1590,10 +1598,6 @@
writer.print(prefix); writer.print("mActivity=");
writer.println(mActivity);
}
- if (mChildFragmentManager != null) {
- writer.print(prefix); writer.print("mChildFragmentManager=");
- writer.println(mChildFragmentManager);
- }
if (mParentFragment != null) {
writer.print(prefix); writer.print("mParentFragment=");
writer.println(mParentFragment);
@@ -1633,7 +1637,7 @@
mLoaderManager.dump(prefix + " ", fd, writer, args);
}
if (mChildFragmentManager != null) {
- writer.print(prefix); writer.println("Child Fragment Manager:");
+ writer.print(prefix); writer.println("Child " + mChildFragmentManager + ":");
mChildFragmentManager.dump(prefix + " ", fd, writer, args);
}
}
@@ -1662,6 +1666,9 @@
}
void performCreate(Bundle savedInstanceState) {
+ if (mChildFragmentManager != null) {
+ mChildFragmentManager.noteStateNotSaved();
+ }
mCalled = false;
onCreate(savedInstanceState);
if (!mCalled) {
@@ -1680,7 +1687,18 @@
}
}
+ View performCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ if (mChildFragmentManager != null) {
+ mChildFragmentManager.noteStateNotSaved();
+ }
+ return onCreateView(inflater, container, savedInstanceState);
+ }
+
void performActivityCreated(Bundle savedInstanceState) {
+ if (mChildFragmentManager != null) {
+ mChildFragmentManager.noteStateNotSaved();
+ }
mCalled = false;
onActivityCreated(savedInstanceState);
if (!mCalled) {
@@ -1713,6 +1731,7 @@
void performResume() {
if (mChildFragmentManager != null) {
+ mChildFragmentManager.noteStateNotSaved();
mChildFragmentManager.execPendingActions();
}
mCalled = false;
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index eaaf0d7..7f11437 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -834,7 +834,9 @@
throw new SuperNotCalledException("Fragment " + f
+ " did not call through to super.onAttach()");
}
- mActivity.onAttachFragment(f);
+ if (f.mParentFragment == null) {
+ mActivity.onAttachFragment(f);
+ }
if (!f.mRetaining) {
f.performCreate(f.mSavedFragmentState);
@@ -844,8 +846,8 @@
// For fragments that are part of the content view
// layout, we need to instantiate the view immediately
// and the inflater will take care of adding it.
- f.mView = f.onCreateView(f.getLayoutInflater(f.mSavedFragmentState),
- null, f.mSavedFragmentState);
+ f.mView = f.performCreateView(f.getLayoutInflater(
+ f.mSavedFragmentState), null, f.mSavedFragmentState);
if (f.mView != null) {
f.mView.setSaveFromParentEnabled(false);
if (f.mHidden) f.mView.setVisibility(View.GONE);
@@ -868,8 +870,8 @@
}
}
f.mContainer = container;
- f.mView = f.onCreateView(f.getLayoutInflater(f.mSavedFragmentState),
- container, f.mSavedFragmentState);
+ f.mView = f.performCreateView(f.getLayoutInflater(
+ f.mSavedFragmentState), container, f.mSavedFragmentState);
if (f.mView != null) {
f.mView.setSaveFromParentEnabled(false);
if (container != null) {
@@ -885,7 +887,7 @@
f.onViewCreated(f.mView, f.mSavedFragmentState);
}
}
-
+
f.performActivityCreated(f.mSavedFragmentState);
if (f.mView != null) {
f.restoreViewState(f.mSavedFragmentState);
@@ -1824,7 +1826,7 @@
public void dispatchDestroyView() {
moveToState(Fragment.CREATED, false);
}
-
+
public void dispatchDestroy() {
mDestroyed = true;
execPendingActions();
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 48d84c1..3c2d164 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -183,8 +183,6 @@
* on top of the lock screen while secured. There is no activity stack when
* this flag is used, so launching more than one activity is strongly
* discouraged.
- *
- * @hide
*/
public static final String INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE =
"android.media.action.STILL_IMAGE_CAMERA_SECURE";
diff --git a/core/tests/coretests/apks/FrameworkCoreTests_apk.mk b/core/tests/coretests/apks/FrameworkCoreTests_apk.mk
index ac545ca..1e03270 100644
--- a/core/tests/coretests/apks/FrameworkCoreTests_apk.mk
+++ b/core/tests/coretests/apks/FrameworkCoreTests_apk.mk
@@ -7,6 +7,9 @@
# Make sure every package name gets the FrameworkCoreTests_ prefix.
LOCAL_PACKAGE_NAME := FrameworkCoreTests_$(LOCAL_PACKAGE_NAME)
+# Every package should have a native library
+LOCAL_JNI_SHARED_LIBRARIES := libframeworks_coretests_jni
+
FrameworkCoreTests_all_apks += $(LOCAL_PACKAGE_NAME)
include $(BUILD_PACKAGE)
diff --git a/core/tests/coretests/apks/install_jni_lib/Android.mk b/core/tests/coretests/apks/install_jni_lib/Android.mk
new file mode 100644
index 0000000..de2993a
--- /dev/null
+++ b/core/tests/coretests/apks/install_jni_lib/Android.mk
@@ -0,0 +1,28 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ com_android_frameworks_coretests_JNITest.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libnativehelper
+
+LOCAL_MODULE := libframeworks_coretests_jni
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp b/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp
new file mode 100644
index 0000000..957fc4a
--- /dev/null
+++ b/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include "nativehelper/JNIHelp.h"
+
+namespace android {
+
+static jint checkFunction(JNIEnv*, jclass) {
+ return 1;
+}
+
+static JNINativeMethod sMethods[] = {
+ /* name, signature, funcPtr */
+ { "checkFunction", "()I", (void*) checkFunction },
+};
+
+int register_com_android_framework_coretests_JNITests(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "com/android/framework/coretests/JNITests", sMethods,
+ NELEM(sMethods));
+}
+
+}
+
+/*
+ * JNI Initialization
+ */
+jint JNI_OnLoad(JavaVM *jvm, void *reserved) {
+ JNIEnv *e;
+ int status;
+
+ // Check JNI version
+ if (jvm->GetEnv((void **) &e, JNI_VERSION_1_6)) {
+ return JNI_ERR;
+ }
+
+ if ((status = android::register_com_android_framework_coretests_JNITests(e)) < 0) {
+ return JNI_ERR;
+ }
+
+ return JNI_VERSION_1_6;
+}
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index f46478c..1868d1c 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -16,6 +16,8 @@
package android.content.pm;
+import static libcore.io.OsConstants.*;
+
import com.android.frameworks.coretests.R;
import com.android.internal.content.PackageHelper;
@@ -32,9 +34,11 @@
import android.os.Environment;
import android.os.FileUtils;
import android.os.IBinder;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StatFs;
+import android.os.SystemClock;
import android.os.storage.IMountService;
import android.os.storage.StorageListener;
import android.os.storage.StorageManager;
@@ -52,6 +56,12 @@
import java.io.InputStream;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import libcore.io.ErrnoException;
+import libcore.io.Libcore;
+import libcore.io.StructStat;
public class PackageManagerTests extends AndroidTestCase {
private static final boolean localLOGV = true;
@@ -404,15 +414,12 @@
if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
assertTrue("The application should be installed forward locked",
(info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
- assertTrue("The APK path (" + srcPath + ") should start with "
- + SECURE_CONTAINERS_PREFIX,
- srcPath.startsWith(SECURE_CONTAINERS_PREFIX));
- assertTrue("The public APK path (" + publicSrcPath + ") should start with "
- + SECURE_CONTAINERS_PREFIX,
- publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX));
- assertTrue("The native library path (" + info.nativeLibraryDir
- + ") should start with " + SECURE_CONTAINERS_PREFIX,
- info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
+ assertStartsWith("The APK path should point to the ASEC",
+ SECURE_CONTAINERS_PREFIX, srcPath);
+ assertStartsWith("The public APK path should point to the ASEC",
+ SECURE_CONTAINERS_PREFIX, publicSrcPath);
+ assertStartsWith("The native library path should point to the ASEC",
+ SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir);
try {
String compatLib = new File(info.dataDir + "/lib").getCanonicalPath();
assertEquals("The compatibility lib directory should be a symbolic link to "
@@ -425,7 +432,14 @@
assertFalse((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
assertEquals(srcPath, appInstallPath);
assertEquals(publicSrcPath, appInstallPath);
- assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath()));
+ assertStartsWith("Native library should point to shared lib directory",
+ dataDir.getPath(),
+ info.nativeLibraryDir);
+ assertDirOwnerGroupPerms(
+ "Native library directory should be owned by system:system and 0755",
+ Process.SYSTEM_UID, Process.SYSTEM_UID,
+ S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH,
+ info.nativeLibraryDir);
}
assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
@@ -435,8 +449,7 @@
nativeLibDir.exists());
try {
assertEquals("Native library dir should not be a symlink",
- info.nativeLibraryDir,
- nativeLibDir.getCanonicalPath());
+ info.nativeLibraryDir, nativeLibDir.getCanonicalPath());
} catch (IOException e) {
fail("Can't read " + nativeLibDir.getPath());
}
@@ -453,14 +466,12 @@
(info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
// Might need to check:
// ((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0)
- assertTrue("The APK path (" + srcPath + ") should start with "
- + SECURE_CONTAINERS_PREFIX, srcPath.startsWith(SECURE_CONTAINERS_PREFIX));
- assertTrue("The public APK path (" + publicSrcPath + ") should start with "
- + SECURE_CONTAINERS_PREFIX,
- publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX));
- assertTrue("The native library path (" + info.nativeLibraryDir
- + ") should start with " + SECURE_CONTAINERS_PREFIX,
- info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
+ assertStartsWith("The APK path should point to the ASEC",
+ SECURE_CONTAINERS_PREFIX, srcPath);
+ assertStartsWith("The public APK path should point to the ASEC",
+ SECURE_CONTAINERS_PREFIX, publicSrcPath);
+ assertStartsWith("The native library path should point to the ASEC",
+ SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir);
// Make sure the native library in /data/data/<app>/lib is a
// symlink to the ASEC
@@ -483,6 +494,66 @@
}
}
+ private void assertDirOwnerGroupPerms(String reason, int uid, int gid, int perms, String path) {
+ final StructStat stat;
+
+ try {
+ stat = Libcore.os.lstat(path);
+ } catch (ErrnoException e) {
+ throw new AssertionError(reason + "\n" + "Got: " + path + " does not exist");
+ }
+
+ StringBuilder sb = new StringBuilder();
+
+ if (!S_ISDIR(stat.st_mode)) {
+ sb.append("\nExpected type: ");
+ sb.append(S_IFDIR);
+ sb.append("\ngot type: ");
+ sb.append((stat.st_mode & S_IFMT));
+ }
+
+ if (stat.st_uid != uid) {
+ sb.append("\nExpected owner: ");
+ sb.append(uid);
+ sb.append("\nGot owner: ");
+ sb.append(stat.st_uid);
+ }
+
+ if (stat.st_gid != gid) {
+ sb.append("\nExpected group: ");
+ sb.append(gid);
+ sb.append("\nGot group: ");
+ sb.append(stat.st_gid);
+ }
+
+ if ((stat.st_mode & ~S_IFMT) != perms) {
+ sb.append("\nExpected permissions: ");
+ sb.append(Integer.toOctalString(perms));
+ sb.append("\nGot permissions: ");
+ sb.append(Integer.toOctalString(stat.st_mode & ~S_IFMT));
+ }
+
+ if (sb.length() > 0) {
+ throw new AssertionError(reason + sb.toString());
+ }
+ }
+
+ private static void assertStartsWith(String prefix, String actual) {
+ assertStartsWith("", prefix, actual);
+ }
+
+ private static void assertStartsWith(String description, String prefix, String actual) {
+ if (!actual.startsWith(prefix)) {
+ StringBuilder sb = new StringBuilder(description);
+ sb.append("\nExpected prefix: ");
+ sb.append(prefix);
+ sb.append("\n got: ");
+ sb.append(actual);
+ sb.append('\n');
+ throw new AssertionError(sb.toString());
+ }
+ }
+
private void assertNotInstalled(String pkgName) {
try {
ApplicationInfo info = getPm().getApplicationInfo(pkgName, 0);
@@ -820,22 +891,51 @@
| PackageManager.INSTALL_EXTERNAL);
}
- /* -------------- Delete tests ---*/
+ /* -------------- Delete tests --- */
private static class DeleteObserver extends IPackageDeleteObserver.Stub {
+ private CountDownLatch mLatch = new CountDownLatch(1);
- public boolean succeeded;
- private boolean doneFlag = false;
+ private int mReturnCode;
- public boolean isDone() {
- return doneFlag;
+ private final String mPackageName;
+
+ private String mObservedPackage;
+
+ public DeleteObserver(String packageName) {
+ mPackageName = packageName;
+ }
+
+ public boolean isSuccessful() {
+ return mReturnCode == PackageManager.DELETE_SUCCEEDED;
}
public void packageDeleted(String packageName, int returnCode) throws RemoteException {
- synchronized(this) {
- this.succeeded = returnCode == PackageManager.DELETE_SUCCEEDED;
- doneFlag = true;
- notifyAll();
+ mObservedPackage = packageName;
+
+ mReturnCode = returnCode;
+
+ mLatch.countDown();
+ }
+
+ public void waitForCompletion(long timeoutMillis) {
+ final long deadline = SystemClock.uptimeMillis() + timeoutMillis;
+
+ long waitTime = timeoutMillis;
+ while (waitTime > 0) {
+ try {
+ boolean done = mLatch.await(waitTime, TimeUnit.MILLISECONDS);
+ if (done) {
+ assertEquals(mPackageName, mObservedPackage);
+ return;
+ }
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ waitTime = deadline - SystemClock.uptimeMillis();
}
+
+ throw new AssertionError("Timeout waiting for package deletion");
}
}
@@ -863,41 +963,40 @@
}
}
- public boolean invokeDeletePackage(final String pkgName, int flags,
- GenericReceiver receiver) throws Exception {
- DeleteObserver observer = new DeleteObserver();
- final boolean received = false;
+ public boolean invokeDeletePackage(final String pkgName, int flags, GenericReceiver receiver)
+ throws Exception {
+ ApplicationInfo info = getPm().getApplicationInfo(pkgName,
+ PackageManager.GET_UNINSTALLED_PACKAGES);
+
mContext.registerReceiver(receiver, receiver.filter);
try {
- // Wait on observer
- synchronized(observer) {
- synchronized (receiver) {
- getPm().deletePackage(pkgName, observer, flags);
- long waitTime = 0;
- while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
- observer.wait(WAIT_TIME_INCR);
- waitTime += WAIT_TIME_INCR;
- }
- if(!observer.isDone()) {
- throw new Exception("Timed out waiting for packageInstalled callback");
- }
- // Verify we received the broadcast
- waitTime = 0;
- while((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
- receiver.wait(WAIT_TIME_INCR);
- waitTime += WAIT_TIME_INCR;
- }
- if(!receiver.isDone()) {
- throw new Exception("Timed out waiting for PACKAGE_REMOVED notification");
- }
- return receiver.received;
- }
+ DeleteObserver observer = new DeleteObserver(pkgName);
+
+ getPm().deletePackage(pkgName, observer, flags);
+ observer.waitForCompletion(MAX_WAIT_TIME);
+
+ assertUninstalled(info);
+
+ // Verify we received the broadcast
+ long waitTime = 0;
+ while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) {
+ receiver.wait(WAIT_TIME_INCR);
+ waitTime += WAIT_TIME_INCR;
}
+ if (!receiver.isDone()) {
+ throw new Exception("Timed out waiting for PACKAGE_REMOVED notification");
+ }
+ return receiver.received;
} finally {
mContext.unregisterReceiver(receiver);
}
}
+ private static void assertUninstalled(ApplicationInfo info) throws Exception {
+ File nativeLibraryFile = new File(info.nativeLibraryDir);
+ assertFalse("Native library directory should be erased", nativeLibraryFile.exists());
+ }
+
public void deleteFromRawResource(int iFlags, int dFlags) throws Exception {
InstallParams ip = sampleInstallFromRawResource(iFlags, false);
boolean retainData = ((dFlags & PackageManager.DELETE_KEEP_DATA) != 0);
@@ -1212,11 +1311,29 @@
return;
}
Runtime.getRuntime().gc();
- Log.i(TAG, "Deleting package : " + ip.pkg.packageName);
- getPm().deletePackage(ip.pkg.packageName, null, 0);
- File outFile = new File(ip.pkg.mScanPath);
- if (outFile != null && outFile.exists()) {
- outFile.delete();
+
+ final String packageName = ip.pkg.packageName;
+ Log.i(TAG, "Deleting package : " + packageName);
+
+ ApplicationInfo info = null;
+ try {
+ info = getPm().getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
+ } catch (NameNotFoundException ignored) {
+ }
+
+ DeleteObserver observer = new DeleteObserver(packageName);
+ getPm().deletePackage(packageName, observer, 0);
+ observer.waitForCompletion(MAX_WAIT_TIME);
+
+ try {
+ if (info != null) {
+ assertUninstalled(info);
+ }
+ } finally {
+ File outFile = new File(ip.pkg.mScanPath);
+ if (outFile != null && outFile.exists()) {
+ outFile.delete();
+ }
}
}
@@ -1230,7 +1347,10 @@
PackageManager.GET_UNINSTALLED_PACKAGES);
if (info != null) {
- getPm().deletePackage(pkgName, null, 0);
+ DeleteObserver observer = new DeleteObserver(pkgName);
+ getPm().deletePackage(pkgName, observer, 0);
+ observer.waitForCompletion(MAX_WAIT_TIME);
+ assertUninstalled(info);
}
} catch (NameNotFoundException e) {
}
@@ -1587,16 +1707,16 @@
if ((moveFlags & PackageManager.MOVE_INTERNAL) != 0) {
assertTrue("ApplicationInfo.FLAG_EXTERNAL_STORAGE flag should NOT be set",
(info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0);
- assertTrue("ApplicationInfo.nativeLibraryDir should start with " + info.dataDir,
- info.nativeLibraryDir.startsWith(info.dataDir));
- } else if ((moveFlags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0){
+ assertStartsWith("Native library dir should be in dataDir",
+ info.dataDir, info.nativeLibraryDir);
+ } else if ((moveFlags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0) {
assertTrue("ApplicationInfo.FLAG_EXTERNAL_STORAGE flag should be set",
(info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
- assertTrue("ApplicationInfo.nativeLibraryDir should start with " + SECURE_CONTAINERS_PREFIX,
- info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
+ assertStartsWith("Native library dir should point to ASEC",
+ SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir);
final File nativeLibSymLink = new File(info.dataDir, "lib");
- assertTrue("The data directory should have a 'lib' symlink that points to the ASEC container",
- nativeLibSymLink.getCanonicalPath().startsWith(SECURE_CONTAINERS_PREFIX));
+ assertStartsWith("The data directory should have a 'lib' symlink that points to the ASEC container",
+ SECURE_CONTAINERS_PREFIX, nativeLibSymLink.getCanonicalPath());
}
}
} catch (NameNotFoundException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index e9dd70a..f374c11 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -22,18 +22,15 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.CursorLoader;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.Loader;
import android.content.res.Resources;
import android.database.Cursor;
-import android.database.DataSetObserver;
import android.graphics.drawable.ClipDrawable;
import android.hardware.display.DisplayManager;
import android.hardware.display.WifiDisplay;
import android.hardware.display.WifiDisplayStatus;
-import android.hardware.input.KeyboardLayout;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.Settings;
@@ -44,12 +41,8 @@
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
-import android.widget.CheckedTextView;
import android.widget.ListView;
-import android.widget.RadioButton;
import android.widget.TextView;
-import android.widget.Toast;
-import android.widget.ListAdapter;
import java.util.ArrayList;
import java.util.Comparator;
@@ -411,7 +404,7 @@
@Override
public void onLoadComplete(Loader<Cursor> loader,
Cursor cursor) {
- if (cursor.moveToFirst()) {
+ if (cursor != null && cursor.moveToFirst()) {
String name = cursor.getString(0); // DISPLAY_NAME
mModel.setUserTileInfo(name);
/*
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
index 95772af..7554236 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
@@ -142,7 +142,9 @@
protected void launchCamera() {
if (mLockPatternUtils.isSecure()) {
// Launch the secure version of the camera
- launchActivity(new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE), true);
+ Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
+ intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ launchActivity(intent, true);
} else {
// Launch the normal camera
launchActivity(new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA), false);
@@ -262,7 +264,7 @@
* See {@link WindowManager#FLAG_SHOW_WHEN_LOCKED}
*/
private void launchActivity(final Intent intent, boolean showsWhileLocked) {
- intent.setFlags(
+ intent.addFlags(
Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index 7144808..2975880 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -1551,8 +1551,12 @@
}
}
} else {
- didSomething = collectForceStopServicesLocked(name, userId, evenPersistent,
- doit, mServiceMap.mServicesByNamePerUser.get(userId), services);
+ HashMap<ComponentName, ServiceRecord> items
+ = mServiceMap.mServicesByNamePerUser.get(userId);
+ if (items != null) {
+ didSomething = collectForceStopServicesLocked(name, userId, evenPersistent,
+ doit, items, services);
+ }
}
int N = services.size();
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index ca45946..0b2d769 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -546,7 +546,7 @@
*/
final ArrayList mCancelledThumbnails = new ArrayList();
- final ProviderMap mProviderMap = new ProviderMap();
+ final ProviderMap mProviderMap;
/**
* List of content providers who have clients waiting for them. The
@@ -1511,6 +1511,7 @@
mBroadcastQueues[1] = mBgBroadcastQueue;
mServices = new ActiveServices(this);
+ mProviderMap = new ProviderMap(this);
File dataDir = Environment.getDataDirectory();
File systemDir = new File(dataDir, "system");
@@ -1792,7 +1793,7 @@
// Also don't let it kick out the first few "real" hidden processes.
skipTop = ProcessList.MIN_HIDDEN_APPS;
}
-
+
while (i >= 0) {
ProcessRecord p = mLruProcesses.get(i);
// If this app shouldn't be in front of the first N background
@@ -2680,7 +2681,7 @@
}
final long origId = Binder.clearCallingIdentity();
boolean res = mMainStack.requestFinishActivityLocked(token, resultCode,
- resultData, "app-request");
+ resultData, "app-request", true);
Binder.restoreCallingIdentity(origId);
return res;
}
@@ -2710,7 +2711,7 @@
int index = mMainStack.indexOfTokenLocked(r.appToken);
if (index >= 0) {
mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
- null, "finish-heavy");
+ null, "finish-heavy", true);
}
}
}
@@ -3627,7 +3628,7 @@
ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
r.stack.finishActivityLocked(r, i,
- Activity.RESULT_CANCELED, null, "close-sys");
+ Activity.RESULT_CANCELED, null, "close-sys", true);
}
}
@@ -6972,7 +6973,7 @@
if (count > 1) {
final long origId = Binder.clearCallingIdentity();
mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
- count-1, Activity.RESULT_CANCELED, null, "unhandled-back");
+ count-1, Activity.RESULT_CANCELED, null, "unhandled-back", true);
Binder.restoreCallingIdentity(origId);
}
}
@@ -7891,7 +7892,8 @@
if (r.app == app) {
Slog.w(TAG, " Force finishing activity "
+ r.intent.getComponent().flattenToShortString());
- r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED, null, "crashed");
+ r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
+ null, "crashed", false);
}
}
if (!app.persistent) {
@@ -7926,7 +7928,7 @@
+ r.intent.getComponent().flattenToShortString());
int index = mMainStack.indexOfActivityLocked(r);
r.stack.finishActivityLocked(r, index,
- Activity.RESULT_CANCELED, null, "crashed");
+ Activity.RESULT_CANCELED, null, "crashed", false);
// Also terminate any activities below it that aren't yet
// stopped, to avoid a situation where one will get
// re-start our crashing activity once it gets resumed again.
@@ -7940,7 +7942,7 @@
Slog.w(TAG, " Force finishing activity "
+ r.intent.getComponent().flattenToShortString());
r.stack.finishActivityLocked(r, index,
- Activity.RESULT_CANCELED, null, "crashed");
+ Activity.RESULT_CANCELED, null, "crashed", false);
}
}
}
@@ -12305,7 +12307,7 @@
for (int i = start; i > finishTo; i--) {
ActivityRecord r = history.get(i);
mMainStack.requestFinishActivityLocked(r.appToken, resultCode, resultData,
- "navigate-up");
+ "navigate-up", true);
// Only return the supplied result for the first activity finished
resultCode = Activity.RESULT_CANCELED;
resultData = null;
@@ -12331,7 +12333,7 @@
foundParentInTask = false;
}
mMainStack.requestFinishActivityLocked(parent.appToken, resultCode,
- resultData, "navigate-up");
+ resultData, "navigate-up", true);
}
}
Binder.restoreCallingIdentity(origId);
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index c70650d..009fb5d 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -333,7 +333,6 @@
state = ActivityState.INITIALIZING;
frontOfTask = false;
launchFailed = false;
- haveState = false;
stopped = false;
delayedResume = false;
finishing = false;
@@ -347,6 +346,11 @@
idle = false;
hasBeenLaunched = false;
+ // This starts out true, since the initial state of an activity
+ // is that we have everything, and we shouldn't never consider it
+ // lacking in state to be removed if it dies.
+ haveState = true;
+
if (aInfo != null) {
if (aInfo.targetActivity == null
|| aInfo.launchMode == ActivityInfo.LAUNCH_MULTIPLE
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 895b52a..bc835b6 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -725,7 +725,7 @@
+ ", giving up", e);
mService.appDiedLocked(app, app.pid, app.thread);
requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
- "2nd-crash");
+ "2nd-crash", false);
return false;
}
@@ -1092,7 +1092,7 @@
if (prev != null) {
if (prev.finishing) {
if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
- prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
+ prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
} else if (prev.app != null) {
if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
if (prev.waitingVisible) {
@@ -1504,7 +1504,7 @@
Slog.d(TAG, "no-history finish of " + last + " on new resume");
}
requestFinishActivityLocked(last.appToken, Activity.RESULT_CANCELED, null,
- "no-history");
+ "no-history", false);
}
}
@@ -1726,7 +1726,7 @@
// activity and try the next one.
Slog.w(TAG, "Exception thrown during resume of " + next, e);
requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
- "resume-exception");
+ "resume-exception", true);
return true;
}
@@ -2080,7 +2080,7 @@
continue;
}
if (finishActivityLocked(p, srcPos,
- Activity.RESULT_CANCELED, null, "reset")) {
+ Activity.RESULT_CANCELED, null, "reset", false)) {
replyChainEnd--;
srcPos--;
}
@@ -2143,7 +2143,7 @@
continue;
}
if (finishActivityLocked(p, srcPos,
- Activity.RESULT_CANCELED, null, "reset")) {
+ Activity.RESULT_CANCELED, null, "reset", false)) {
taskTopI--;
lastReparentPos--;
replyChainEnd--;
@@ -2200,7 +2200,7 @@
}
if (p.intent.getComponent().equals(target.intent.getComponent())) {
if (finishActivityLocked(p, j,
- Activity.RESULT_CANCELED, null, "replace")) {
+ Activity.RESULT_CANCELED, null, "replace", false)) {
taskTopI--;
lastReparentPos--;
}
@@ -2270,7 +2270,7 @@
continue;
}
if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
- null, "clear")) {
+ null, "clear", false)) {
i--;
}
}
@@ -2284,7 +2284,7 @@
int index = indexOfTokenLocked(ret.appToken);
if (index >= 0) {
finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
- null, "clear");
+ null, "clear", false);
}
return null;
}
@@ -2313,7 +2313,7 @@
continue;
}
if (!finishActivityLocked(r, i, Activity.RESULT_CANCELED,
- null, "clear")) {
+ null, "clear", false)) {
i++;
}
}
@@ -2579,6 +2579,7 @@
mDismissKeyguardOnNextActivity = false;
mService.mWindowManager.dismissKeyguard();
}
+ Slog.i(TAG, "DONE STARTING!");
return err;
}
@@ -3319,7 +3320,7 @@
Slog.d(TAG, "no-history finish of " + r);
}
requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
- "no-history");
+ "no-history", false);
} else {
if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r
+ " on stop because we're just sleeping");
@@ -3531,7 +3532,7 @@
ActivityRecord r = (ActivityRecord)stops.get(i);
synchronized (mService) {
if (r.finishing) {
- finishCurrentActivityLocked(r, FINISH_IMMEDIATELY);
+ finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
} else {
stopActivityLocked(r);
}
@@ -3585,7 +3586,7 @@
* some reason it is being left as-is.
*/
final boolean requestFinishActivityLocked(IBinder token, int resultCode,
- Intent resultData, String reason) {
+ Intent resultData, String reason, boolean oomAdj) {
int index = indexOfTokenLocked(token);
if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(
TAG, "Finishing activity @" + index + ": token=" + token
@@ -3596,7 +3597,7 @@
}
ActivityRecord r = mHistory.get(index);
- finishActivityLocked(r, index, resultCode, resultData, reason);
+ finishActivityLocked(r, index, resultCode, resultData, reason, oomAdj);
return true;
}
@@ -3613,10 +3614,11 @@
if ((r.resultWho == null && resultWho == null) ||
(r.resultWho != null && r.resultWho.equals(resultWho))) {
finishActivityLocked(r, i,
- Activity.RESULT_CANCELED, null, "request-sub");
+ Activity.RESULT_CANCELED, null, "request-sub", false);
}
}
}
+ mService.updateOomAdjLocked();
}
final boolean finishActivityAffinityLocked(IBinder token) {
@@ -3639,7 +3641,8 @@
if (cur.taskAffinity != null && !cur.taskAffinity.equals(r.taskAffinity)) {
break;
}
- finishActivityLocked(cur, index, Activity.RESULT_CANCELED, null, "request-affinity");
+ finishActivityLocked(cur, index, Activity.RESULT_CANCELED, null,
+ "request-affinity", true);
index--;
}
return true;
@@ -3677,16 +3680,16 @@
* list, or false if it is still in the list and will be removed later.
*/
final boolean finishActivityLocked(ActivityRecord r, int index,
- int resultCode, Intent resultData, String reason) {
- return finishActivityLocked(r, index, resultCode, resultData, reason, false);
+ int resultCode, Intent resultData, String reason, boolean oomAdj) {
+ return finishActivityLocked(r, index, resultCode, resultData, reason, false, oomAdj);
}
/**
* @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.
*/
- final boolean finishActivityLocked(ActivityRecord r, int index,
- int resultCode, Intent resultData, String reason, boolean immediate) {
+ final boolean finishActivityLocked(ActivityRecord r, int index, int resultCode,
+ Intent resultData, String reason, boolean immediate, boolean oomAdj) {
if (r.finishing) {
Slog.w(TAG, "Duplicate finish request for " + r);
return false;
@@ -3730,7 +3733,7 @@
if (immediate) {
return finishCurrentActivityLocked(r, index,
- FINISH_IMMEDIATELY) == null;
+ FINISH_IMMEDIATELY, oomAdj) == null;
} else if (mResumedActivity == r) {
boolean endTask = index <= 0
|| (mHistory.get(index-1)).task != r.task;
@@ -3754,7 +3757,7 @@
// it is done pausing; else we can just directly finish it here.
if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
return finishCurrentActivityLocked(r, index,
- FINISH_AFTER_PAUSE) == null;
+ FINISH_AFTER_PAUSE, oomAdj) == null;
} else {
if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
}
@@ -3767,17 +3770,17 @@
private static final int FINISH_AFTER_VISIBLE = 2;
private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
- int mode) {
+ int mode, boolean oomAdj) {
final int index = indexOfActivityLocked(r);
if (index < 0) {
return null;
}
- return finishCurrentActivityLocked(r, index, mode);
+ return finishCurrentActivityLocked(r, index, mode, oomAdj);
}
private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
- int index, int mode) {
+ int index, int mode, boolean oomAdj) {
// First things first: if this activity is currently visible,
// and the resumed activity is not yet visible, then hold off on
// finishing until the resumed one becomes visible.
@@ -3796,7 +3799,9 @@
if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
+ " (finish requested)");
r.state = ActivityState.STOPPING;
- mService.updateOomAdjLocked();
+ if (oomAdj) {
+ mService.updateOomAdjLocked();
+ }
return r;
}
@@ -3816,7 +3821,8 @@
|| prevState == ActivityState.INITIALIZING) {
// If this activity is already stopped, we can just finish
// it right now.
- boolean activityRemoved = destroyActivityLocked(r, true, true, "finish-imm");
+ boolean activityRemoved = destroyActivityLocked(r, true,
+ oomAdj, "finish-imm");
if (activityRemoved) {
resumeTopActivityLocked(null);
}
@@ -4008,9 +4014,8 @@
ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
}
if (r.app.activities.size() == 0) {
- // No longer have activities, so update location in
- // LRU list.
- mService.updateLruProcessLocked(r.app, oomAdj, false);
+ // No longer have activities, so update oom adj.
+ mService.updateOomAdjLocked();
}
}
diff --git a/services/java/com/android/server/am/ProviderMap.java b/services/java/com/android/server/am/ProviderMap.java
index 2d7167b..9dbf5f5 100644
--- a/services/java/com/android/server/am/ProviderMap.java
+++ b/services/java/com/android/server/am/ProviderMap.java
@@ -18,7 +18,6 @@
import android.content.ComponentName;
import android.os.Binder;
-import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Slog;
@@ -31,8 +30,6 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
/**
* Keeps track of content providers by authority (name) and class. It separates the mapping by
@@ -44,6 +41,8 @@
private static final boolean DBG = false;
+ private final ActivityManagerService mAm;
+
private final HashMap<String, ContentProviderRecord> mSingletonByName
= new HashMap<String, ContentProviderRecord>();
private final HashMap<ComponentName, ContentProviderRecord> mSingletonByClass
@@ -54,6 +53,10 @@
private final SparseArray<HashMap<ComponentName, ContentProviderRecord>> mProvidersByClassPerUser
= new SparseArray<HashMap<ComponentName, ContentProviderRecord>>();
+ ProviderMap(ActivityManagerService am) {
+ mAm = am;
+ }
+
ContentProviderRecord getProviderByName(String name) {
return getProviderByName(name, -1);
}
@@ -217,8 +220,12 @@
}
}
} else {
- didSomething |= collectForceStopProvidersLocked(name, appId, doit, evenPersistent,
- userId, getProvidersByClass(userId), result);
+ HashMap<ComponentName, ContentProviderRecord> items
+ = getProvidersByClass(userId);
+ if (items != null) {
+ didSomething |= collectForceStopProvidersLocked(name, appId, doit,
+ evenPersistent, userId, items, result);
+ }
}
return didSomething;
}
@@ -279,30 +286,33 @@
protected boolean dumpProvider(FileDescriptor fd, PrintWriter pw, String name, String[] args,
int opti, boolean dumpAll) {
+ ArrayList<ContentProviderRecord> allProviders = new ArrayList<ContentProviderRecord>();
ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>();
- if ("all".equals(name)) {
- synchronized (this) {
- for (ContentProviderRecord r1 : getProvidersByClass(-1).values()) {
- providers.add(r1);
- }
- }
- } else {
- ComponentName componentName = name != null
- ? ComponentName.unflattenFromString(name) : null;
- int objectId = 0;
- if (componentName == null) {
- // Not a '/' separated full component name; maybe an object ID?
- try {
- objectId = Integer.parseInt(name, 16);
- name = null;
- componentName = null;
- } catch (RuntimeException e) {
- }
+ synchronized (mAm) {
+ allProviders.addAll(mSingletonByClass.values());
+ for (int i=0; i<mProvidersByClassPerUser.size(); i++) {
+ allProviders.addAll(mProvidersByClassPerUser.valueAt(i).values());
}
- synchronized (this) {
- for (ContentProviderRecord r1 : getProvidersByClass(-1).values()) {
+ if ("all".equals(name)) {
+ providers.addAll(allProviders);
+ } else {
+ ComponentName componentName = name != null
+ ? ComponentName.unflattenFromString(name) : null;
+ int objectId = 0;
+ if (componentName == null) {
+ // Not a '/' separated full component name; maybe an object ID?
+ try {
+ objectId = Integer.parseInt(name, 16);
+ name = null;
+ componentName = null;
+ } catch (RuntimeException e) {
+ }
+ }
+
+ for (int i=0; i<allProviders.size(); i++) {
+ ContentProviderRecord r1 = allProviders.get(i);
if (componentName != null) {
if (r1.name.equals(componentName)) {
providers.add(r1);
@@ -340,7 +350,7 @@
private void dumpProvider(String prefix, FileDescriptor fd, PrintWriter pw,
final ContentProviderRecord r, String[] args, boolean dumpAll) {
String innerPrefix = prefix + " ";
- synchronized (this) {
+ synchronized (mAm) {
pw.print(prefix); pw.print("PROVIDER ");
pw.print(r);
pw.print(" pid=");
diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java
index e11d454..39f2418 100644
--- a/services/java/com/android/server/display/DisplayManagerService.java
+++ b/services/java/com/android/server/display/DisplayManagerService.java
@@ -352,7 +352,9 @@
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
- mWifiDisplayAdapter.requestScanLocked();
+ if (mWifiDisplayAdapter != null) {
+ mWifiDisplayAdapter.requestScanLocked();
+ }
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -372,7 +374,9 @@
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
- mWifiDisplayAdapter.requestConnectLocked(address);
+ if (mWifiDisplayAdapter != null) {
+ mWifiDisplayAdapter.requestConnectLocked(address);
+ }
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -389,7 +393,9 @@
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
- mWifiDisplayAdapter.requestDisconnectLocked();
+ if (mWifiDisplayAdapter != null) {
+ mWifiDisplayAdapter.requestDisconnectLocked();
+ }
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -406,7 +412,11 @@
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
- return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
+ if (mWifiDisplayAdapter != null) {
+ return mWifiDisplayAdapter.getWifiDisplayStatusLocked();
+ } else {
+ return new WifiDisplayStatus();
+ }
}
} finally {
Binder.restoreCallingIdentity(token);
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index d0f2ed1..4bb6e38 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -8118,10 +8118,7 @@
// Delete application code and resources
if (deleteCodeAndResources) {
- // TODO can pick up from PackageSettings as well
- int installFlags = isExternal(ps) ? PackageManager.INSTALL_EXTERNAL : 0;
- installFlags |= isForwardLocked(ps) ? PackageManager.INSTALL_FORWARD_LOCK : 0;
- outInfo.args = createInstallArgs(installFlags, ps.codePathString,
+ outInfo.args = createInstallArgs(packageFlagsToInstallFlags(ps), ps.codePathString,
ps.resourcePathString, ps.nativeLibraryPathString);
}
return true;
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index b85353c..b075da3 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -566,6 +566,10 @@
if (p.signatures.mSignatures == null) {
p.signatures.assignSignatures(pkg.mSignatures);
}
+ // Update flags if needed.
+ if (pkg.applicationInfo.flags != p.pkgFlags) {
+ p.pkgFlags = pkg.applicationInfo.flags;
+ }
// If this app defines a shared user id initialize
// the shared user signatures as well.
if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
@@ -2616,10 +2620,10 @@
pw.print(" installerPackageName="); pw.println(ps.installerPackageName);
}
pw.print(" signatures="); pw.println(ps.signatures);
- pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
- pw.print(" haveGids="); pw.println(ps.haveGids);
- pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
- pw.print(" installStatus="); pw.println(ps.installStatus);
+ pw.print(" permissionsFixed="); pw.println(ps.permissionsFixed);
+ pw.print(" haveGids="); pw.println(ps.haveGids);
+ pw.print(" pkgFlags="); printFlags(pw, ps.pkgFlags, FLAG_DUMP_SPEC);
+ pw.print(" installStatus="); pw.println(ps.installStatus);
for (UserInfo user : users) {
pw.print(" User "); pw.print(user.id); pw.print(": ");
pw.print(" installed=");
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index 482f43e..d9b0681 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -34,7 +34,6 @@
endif
-LOCAL_C_INCLUDES += external/expat/lib
LOCAL_C_INCLUDES += external/libpng
LOCAL_C_INCLUDES += external/zlib
LOCAL_C_INCLUDES += build/libs/host/include
diff --git a/tools/aapt/StringPool.h b/tools/aapt/StringPool.h
index d501008..16050b2 100644
--- a/tools/aapt/StringPool.h
+++ b/tools/aapt/StringPool.h
@@ -21,7 +21,7 @@
#include <ctype.h>
#include <errno.h>
-#include <expat.h>
+#include <libexpat/expat.h>
using namespace android;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
index 117af82..863a055 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
@@ -124,7 +124,8 @@
"name='(.*)' " +
"config_methods=(0x[0-9a-fA-F]+) " +
"dev_capab=(0x[0-9a-fA-F]+) " +
- "group_capab=(0x[0-9a-fA-F]+)"
+ "group_capab=(0x[0-9a-fA-F]+)" +
+ "( wfd_dev_info=0x000006([0-9a-fA-F]{12}))?"
);
/** 2 token device address pattern
@@ -153,7 +154,7 @@
* @param string formats supported include
* P2P-DEVICE-FOUND fa:7b:7a:42:02:13 p2p_dev_addr=fa:7b:7a:42:02:13
* pri_dev_type=1-0050F204-1 name='p2p-TEST1' config_methods=0x188 dev_capab=0x27
- * group_capab=0x0
+ * group_capab=0x0 wfd_dev_info=000006015d022a0032
*
* P2P-DEVICE-LOST p2p_dev_addr=fa:7b:7a:42:02:13
*
@@ -205,6 +206,12 @@
wpsConfigMethodsSupported = parseHex(match.group(6));
deviceCapability = parseHex(match.group(7));
groupCapability = parseHex(match.group(8));
+ if (match.group(9) != null) {
+ String str = match.group(10);
+ wfdInfo = new WifiP2pWfdInfo(parseHex(str.substring(0,4)),
+ parseHex(str.substring(4,8)),
+ parseHex(str.substring(8,12)));
+ }
break;
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
index 48cdbc2..2093bda 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
@@ -35,10 +35,9 @@
*/
public class WifiP2pDeviceList implements Parcelable {
- private HashMap<String, WifiP2pDevice> mDevices;
+ private final HashMap<String, WifiP2pDevice> mDevices = new HashMap<String, WifiP2pDevice>();
public WifiP2pDeviceList() {
- mDevices = new HashMap<String, WifiP2pDevice>();
}
/** copy constructor */
@@ -52,7 +51,6 @@
/** @hide */
public WifiP2pDeviceList(ArrayList<WifiP2pDevice> devices) {
- mDevices = new HashMap<String, WifiP2pDevice>();
for (WifiP2pDevice device : devices) {
if (device.deviceAddress != null) {
mDevices.put(device.deviceAddress, device);
@@ -78,6 +76,7 @@
d.wpsConfigMethodsSupported = device.wpsConfigMethodsSupported;
d.deviceCapability = device.deviceCapability;
d.groupCapability = device.groupCapability;
+ d.wfdInfo = device.wfdInfo;
return;
}
//Not found, add a new one
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
index 3459a5a..98f0972 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
@@ -16,6 +16,7 @@
package android.net.wifi.p2p;
import java.util.Collection;
+import java.util.Map;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,8 +33,9 @@
private static final int CREDENTIAL_MAX_NUM = 32;
- private LruCache<Integer, WifiP2pGroup> mGroups;
- private GroupDeleteListener mListener;
+ private final LruCache<Integer, WifiP2pGroup> mGroups;
+ private final GroupDeleteListener mListener;
+
private boolean isClearCalled = false;
public interface GroupDeleteListener {
@@ -41,10 +43,10 @@
}
WifiP2pGroupList() {
- this(null);
+ this(null, null);
}
- WifiP2pGroupList(GroupDeleteListener listener) {
+ WifiP2pGroupList(WifiP2pGroupList source, GroupDeleteListener listener) {
mListener = listener;
mGroups = new LruCache<Integer, WifiP2pGroup>(CREDENTIAL_MAX_NUM) {
@Override
@@ -55,6 +57,12 @@
}
}
};
+
+ if (source != null) {
+ for (Map.Entry<Integer, WifiP2pGroup> item : source.mGroups.snapshot().entrySet()) {
+ mGroups.put(item.getKey(), item.getValue());
+ }
+ }
}
/**
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index a6770bd..3575d97 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -359,8 +359,8 @@
private WifiNative mWifiNative = new WifiNative(mInterface);
private WifiMonitor mWifiMonitor = new WifiMonitor(this, mWifiNative);
- private WifiP2pDeviceList mPeers = new WifiP2pDeviceList();
- private WifiP2pGroupList mGroups = new WifiP2pGroupList(
+ private final WifiP2pDeviceList mPeers = new WifiP2pDeviceList();
+ private final WifiP2pGroupList mGroups = new WifiP2pGroupList(null,
new GroupDeleteListener() {
@Override
public void onDeleteGroup(int netId) {
@@ -370,7 +370,7 @@
sendP2pPersistentGroupsChangedBroadcast();
}
});
- private WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo();
+ private final WifiP2pInfo mWifiP2pInfo = new WifiP2pInfo();
private WifiP2pGroup mGroup;
// Saved WifiP2pConfig for a peer connection
@@ -501,17 +501,20 @@
WifiP2pManager.BUSY);
break;
case WifiP2pManager.REQUEST_PEERS:
- replyToMessage(message, WifiP2pManager.RESPONSE_PEERS, mPeers);
+ replyToMessage(message, WifiP2pManager.RESPONSE_PEERS,
+ new WifiP2pDeviceList(mPeers));
break;
case WifiP2pManager.REQUEST_CONNECTION_INFO:
- replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO, mWifiP2pInfo);
+ replyToMessage(message, WifiP2pManager.RESPONSE_CONNECTION_INFO,
+ new WifiP2pInfo(mWifiP2pInfo));
break;
case WifiP2pManager.REQUEST_GROUP_INFO:
- replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO, mGroup);
+ replyToMessage(message, WifiP2pManager.RESPONSE_GROUP_INFO,
+ mGroup != null ? new WifiP2pGroup(mGroup) : null);
break;
case WifiP2pManager.REQUEST_PERSISTENT_GROUP_INFO:
replyToMessage(message, WifiP2pManager.RESPONSE_PERSISTENT_GROUP_INFO,
- mGroups);
+ new WifiP2pGroupList(mGroups, null));
break;
case WifiP2pManager.SET_DIALOG_LISTENER:
String appPkgName = (String)message.getData().getString(
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
index 9dd3e4a..b6bbfc4 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
@@ -54,6 +54,13 @@
public WifiP2pWfdInfo() {
}
+ public WifiP2pWfdInfo(int devInfo, int ctrlPort, int maxTput) {
+ mWfdEnabled = true;
+ mDeviceInfo = devInfo;
+ mCtrlPort = ctrlPort;
+ mMaxThroughput = maxTput;
+ }
+
public boolean isWfdEnabled() {
return mWfdEnabled;
}