summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/app/Application.java11
-rw-r--r--core/java/android/app/ApplicationThreadNative.java1
-rwxr-xr-x[-rw-r--r--]core/java/android/app/admin/DevicePolicyManager.java6
-rw-r--r--core/java/android/os/SELinux.java105
-rw-r--r--core/java/android/widget/Gallery.java8
-rw-r--r--core/java/android/widget/GridView.java7
-rw-r--r--core/java/android/widget/SimpleExpandableListAdapter.java52
-rw-r--r--core/java/com/android/internal/os/ProcessStats.java4
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuPresenter.java2
-rw-r--r--core/jni/Android.mk7
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/android_os_SELinux.cpp502
-rw-r--r--core/res/res/layout/transient_notification.xml1
-rw-r--r--core/tests/coretests/apks/install_complete_package_info/Android.mk11
-rw-r--r--core/tests/coretests/apks/install_complete_package_info/AndroidManifest.xml54
-rw-r--r--core/tests/coretests/apks/install_complete_package_info/src/com/android/frameworks/coretests/TestActivity.java24
-rw-r--r--core/tests/coretests/apks/install_complete_package_info/src/com/android/frameworks/coretests/TestProvider.java57
-rw-r--r--core/tests/coretests/apks/install_complete_package_info/src/com/android/frameworks/coretests/TestReceiver.java57
-rw-r--r--core/tests/coretests/apks/install_complete_package_info/src/com/android/frameworks/coretests/TestService.java30
-rwxr-xr-xcore/tests/coretests/src/android/content/pm/PackageManagerTests.java89
-rw-r--r--core/tests/coretests/src/android/os/SELinuxTest.java45
-rw-r--r--core/tests/overlaytests/OverlayTestOverlay/Android.mk2
-rw-r--r--core/tests/overlaytests/OverlayTestOverlay/res/drawable-nodpi/default_wallpaper.jpg (renamed from core/tests/overlaytests/OverlayTestOverlay/res/drawable/default_wallpaper.jpg)bin399 -> 399 bytes
-rwxr-xr-xcore/tests/overlaytests/runtests.sh44
24 files changed, 1102 insertions, 19 deletions
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index dd9ea26..3a67cec 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -64,11 +64,12 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 {
}
/**
- * Called when the application is starting, before any other application
- * objects have been created. Implementations should be as quick as
- * possible (for example using lazy initialization of state) since the time
- * spent in this function directly impacts the performance of starting the
- * first activity, service, or receiver in a process.
+ * Called when the application is starting, before any activity, service,
+ * or receiver objects (excluding content providers) have been created.
+ * Implementations should be as quick as possible (for example using
+ * lazy initialization of state) since the time spent in this function
+ * directly impacts the performance of starting the first activity,
+ * service, or receiver in a process.
* If you override this method, be sure to call super.onCreate().
*/
public void onCreate() {
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 3e726e0..8e6278d 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -385,6 +385,7 @@ public abstract class ApplicationThreadNative extends Binder
case SCHEDULE_LOW_MEMORY_TRANSACTION:
{
+ data.enforceInterface(IApplicationThread.descriptor);
scheduleLowMemory();
return true;
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 4ed0766..0b58396 100644..100755
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1008,13 +1008,15 @@ public class DevicePolicyManager {
/**
* Ask the user date be wiped. This will cause the device to reboot,
* erasing all user data while next booting up. External storage such
- * as SD cards will not be erased.
+ * as SD cards will be also erased if the flag {@link #WIPE_EXTERNAL_STORAGE}
+ * is set.
*
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA} to be able to call
* this method; if it has not, a security exception will be thrown.
*
- * @param flags Bit mask of additional options: currently must be 0.
+ * @param flags Bit mask of additional options: currently 0 and
+ * {@link #WIPE_EXTERNAL_STORAGE} are supported.
*/
public void wipeData(int flags) {
if (mService != null) {
diff --git a/core/java/android/os/SELinux.java b/core/java/android/os/SELinux.java
new file mode 100644
index 0000000..90cfa37
--- /dev/null
+++ b/core/java/android/os/SELinux.java
@@ -0,0 +1,105 @@
+package android.os;
+
+import java.io.FileDescriptor;
+
+/**
+ * This class provides access to the centralized jni bindings for
+ * SELinux interaction.
+ * {@hide}
+ */
+public class SELinux {
+
+ /**
+ * Determine whether SELinux is disabled or enabled.
+ * @return a boolean indicating whether SELinux is enabled.
+ */
+ public static final native boolean isSELinuxEnabled();
+
+ /**
+ * Determine whether SELinux is permissive or enforcing.
+ * @return a boolean indicating whether SELinux is enforcing.
+ */
+ public static final native boolean isSELinuxEnforced();
+
+ /**
+ * Set whether SELinux is permissive or enforcing.
+ * @param boolean representing whether to set SELinux to enforcing
+ * @return a boolean representing whether the desired mode was set
+ */
+ public static final native boolean setSELinuxEnforce(boolean value);
+
+ /**
+ * Sets the security context for newly created file objects.
+ * @param context a security context given as a String.
+ * @return a boolean indicating whether the operation succeeded.
+ */
+ public static final native boolean setFSCreateContext(String context);
+
+ /**
+ * Change the security context of an existing file object.
+ * @param path representing the path of file object to relabel.
+ * @param con new security context given as a String.
+ * @return a boolean indicating whether the operation succeeded.
+ */
+ public static final native boolean setFileContext(String path, String context);
+
+ /**
+ * Get the security context of a file object.
+ * @param path the pathname of the file object.
+ * @return a security context given as a String.
+ */
+ public static final native String getFileContext(String path);
+
+ /**
+ * Get the security context of a peer socket.
+ * @param fd FileDescriptor class of the peer socket.
+ * @return a String representing the peer socket security context.
+ */
+ public static final native String getPeerContext(FileDescriptor fd);
+
+ /**
+ * Gets the security context of the current process.
+ * @return a String representing the security context of the current process.
+ */
+ public static final native String getContext();
+
+ /**
+ * Gets the security context of a given process id.
+ * Use of this function is discouraged for Binder transactions.
+ * Use Binder.getCallingSecctx() instead.
+ * @param pid an int representing the process id to check.
+ * @return a String representing the security context of the given pid.
+ */
+ public static final native String getPidContext(int pid);
+
+ /**
+ * Gets a list of the SELinux boolean names.
+ * @return an array of strings containing the SELinux boolean names.
+ */
+ public static final native String[] getBooleanNames();
+
+ /**
+ * Gets the value for the given SELinux boolean name.
+ * @param String The name of the SELinux boolean.
+ * @return a boolean indicating whether the SELinux boolean is set.
+ */
+ public static final native boolean getBooleanValue(String name);
+
+ /**
+ * Sets the value for the given SELinux boolean name.
+ * @param String The name of the SELinux boolean.
+ * @param Boolean The new value of the SELinux boolean.
+ * @return a boolean indicating whether or not the operation succeeded.
+ */
+ public static final native boolean setBooleanValue(String name, boolean value);
+
+ /**
+ * Check permissions between two security contexts.
+ * @param scon The source or subject security context.
+ * @param tcon The target or object security context.
+ * @param tclass The object security class name.
+ * @param perm The permission name.
+ * @return a boolean indicating whether permission was granted.
+ */
+ public static final native boolean checkSELinuxAccess(String scon, String tcon, String tclass, String perm);
+}
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index e4e7239..72e429c 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -1195,15 +1195,15 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList
case KeyEvent.KEYCODE_DPAD_LEFT:
if (movePrevious()) {
playSoundEffect(SoundEffectConstants.NAVIGATION_LEFT);
+ return true;
}
- return true;
-
+ break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
if (moveNext()) {
playSoundEffect(SoundEffectConstants.NAVIGATION_RIGHT);
+ return true;
}
- return true;
-
+ break;
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
mReceivedInvokeKeyDown = true;
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 8975109..ada7dd1 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -2207,8 +2207,13 @@ public class GridView extends AbsListView {
int height = view.getHeight();
if (height > 0) {
final int numColumns = mNumColumns;
- final int whichRow = mFirstPosition / numColumns;
final int rowCount = (mItemCount + numColumns - 1) / numColumns;
+ // In case of stackFromBottom the calculation of whichRow needs
+ // to take into account that counting from the top the first row
+ // might not be entirely filled.
+ final int oddItemsOnFirstRow = isStackFromBottom() ? ((rowCount * numColumns) -
+ mItemCount) : 0;
+ final int whichRow = (mFirstPosition + oddItemsOnFirstRow) / numColumns;
return Math.max(whichRow * 100 - (top * 100) / height +
(int) ((float) mScrollY / getHeight() * rowCount * 100), 0);
}
diff --git a/core/java/android/widget/SimpleExpandableListAdapter.java b/core/java/android/widget/SimpleExpandableListAdapter.java
index 015c169..f514374 100644
--- a/core/java/android/widget/SimpleExpandableListAdapter.java
+++ b/core/java/android/widget/SimpleExpandableListAdapter.java
@@ -38,6 +38,8 @@ import java.util.Map;
*/
public class SimpleExpandableListAdapter extends BaseExpandableListAdapter {
private List<? extends Map<String, ?>> mGroupData;
+ // Keeps track of if a group is currently expanded or not
+ private boolean[] mIsGroupExpanded;
private int mExpandedGroupLayout;
private int mCollapsedGroupLayout;
private String[] mGroupFrom;
@@ -196,6 +198,8 @@ public class SimpleExpandableListAdapter extends BaseExpandableListAdapter {
int childLayout, int lastChildLayout, String[] childFrom,
int[] childTo) {
mGroupData = groupData;
+ // Initially all groups are not expanded
+ mIsGroupExpanded = new boolean[groupData.size()];
mExpandedGroupLayout = expandedGroupLayout;
mCollapsedGroupLayout = collapsedGroupLayout;
mGroupFrom = groupFrom;
@@ -298,4 +302,52 @@ public class SimpleExpandableListAdapter extends BaseExpandableListAdapter {
return true;
}
+ /**
+ * {@inheritDoc}
+ * @return 1 for the last child in a group, 0 for the other children.
+ */
+ @Override
+ public int getChildType(int groupPosition, int childPosition) {
+ final int childrenInGroup = getChildrenCount(groupPosition);
+ return childPosition == childrenInGroup - 1 ? 1 : 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @return 2, one type for the last child in a group, one for the other children.
+ */
+ @Override
+ public int getChildTypeCount() {
+ return 2;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @return 1 for an expanded group view, 0 for a collapsed one.
+ */
+ @Override
+ public int getGroupType(int groupPosition) {
+ return mIsGroupExpanded[groupPosition] ? 1 : 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @return 2, one for a collapsed group view, one for an expanded one.
+ */
+ @Override
+ public int getGroupTypeCount() {
+ return 2;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onGroupCollapsed(int groupPosition) {
+ mIsGroupExpanded[groupPosition] = false;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onGroupExpanded(int groupPosition) {
+ mIsGroupExpanded[groupPosition] = true;
+ }
}
diff --git a/core/java/com/android/internal/os/ProcessStats.java b/core/java/com/android/internal/os/ProcessStats.java
index 1923b86..b1bb8c1 100644
--- a/core/java/com/android/internal/os/ProcessStats.java
+++ b/core/java/com/android/internal/os/ProcessStats.java
@@ -154,7 +154,7 @@ public class ProcessStats {
private boolean mFirst = true;
- private byte[] mBuffer = new byte[256];
+ private byte[] mBuffer = new byte[4096];
/**
* The time in microseconds that the CPU has been running at each speed.
@@ -556,7 +556,7 @@ public class ProcessStats {
private long[] getCpuSpeedTimes(long[] out) {
long[] tempTimes = out;
long[] tempSpeeds = mCpuSpeeds;
- final int MAX_SPEEDS = 20;
+ final int MAX_SPEEDS = 60;
if (out == null) {
tempTimes = new long[MAX_SPEEDS]; // Hopefully no more than that
tempSpeeds = new long[MAX_SPEEDS];
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index 73324c0..cf6029e 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -278,7 +278,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter
*/
public boolean showOverflowMenu() {
if (mReserveOverflow && !isOverflowMenuShowing() && mMenu != null && mMenuView != null &&
- mPostedOpenRunnable == null) {
+ mPostedOpenRunnable == null && !mMenu.getNonActionItems().isEmpty()) {
OverflowPopup popup = new OverflowPopup(mContext, mMenu, mOverflowButton, true);
mPostedOpenRunnable = new OpenOverflowRunnable(popup);
// Post this for later; we might still need a layout for the anchor to be right.
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index c24f6c6..b5a2f98 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -66,6 +66,7 @@ LOCAL_SRC_FILES:= \
android_os_MessageQueue.cpp \
android_os_ParcelFileDescriptor.cpp \
android_os_Parcel.cpp \
+ android_os_SELinux.cpp \
android_os_StatFs.cpp \
android_os_SystemClock.cpp \
android_os_SystemProperties.cpp \
@@ -218,6 +219,12 @@ LOCAL_SHARED_LIBRARIES := \
libharfbuzz \
libz
+ifeq ($(HAVE_SELINUX),true)
+LOCAL_C_INCLUDES += external/libselinux/include
+LOCAL_SHARED_LIBRARIES += libselinux
+LOCAL_CFLAGS += -DHAVE_SELINUX
+endif # HAVE_SELINUX
+
ifeq ($(USE_OPENGL_RENDERER),true)
LOCAL_SHARED_LIBRARIES += libhwui
endif
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 241a905..7a23747 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -133,6 +133,7 @@ extern int register_android_os_Debug(JNIEnv* env);
extern int register_android_os_MessageQueue(JNIEnv* env);
extern int register_android_os_Parcel(JNIEnv* env);
extern int register_android_os_ParcelFileDescriptor(JNIEnv *env);
+extern int register_android_os_SELinux(JNIEnv* env);
extern int register_android_os_StatFs(JNIEnv *env);
extern int register_android_os_SystemProperties(JNIEnv *env);
extern int register_android_os_SystemClock(JNIEnv* env);
@@ -1146,6 +1147,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_os_FileUtils),
REG_JNI(register_android_os_MessageQueue),
REG_JNI(register_android_os_ParcelFileDescriptor),
+ REG_JNI(register_android_os_SELinux),
REG_JNI(register_android_os_StatFs),
REG_JNI(register_android_os_Trace),
REG_JNI(register_android_os_UEventObserver),
diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp
new file mode 100644
index 0000000..eb99d2b
--- /dev/null
+++ b/core/jni/android_os_SELinux.cpp
@@ -0,0 +1,502 @@
+#define LOG_TAG "SELinuxJNI"
+#include <utils/Log.h>
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include "android_runtime/AndroidRuntime.h"
+#ifdef HAVE_SELINUX
+#include "selinux/selinux.h"
+#endif
+#include <errno.h>
+
+namespace android {
+
+ static jboolean isSELinuxDisabled = true;
+
+ static void throw_NullPointerException(JNIEnv *env, const char* msg) {
+ jclass clazz;
+ clazz = env->FindClass("java/lang/NullPointerException");
+ env->ThrowNew(clazz, msg);
+ }
+
+ /*
+ * Function: isSELinuxEnabled
+ * Purpose: checks whether SELinux is enabled/disbaled
+ * Parameters: none
+ * Return value : true (enabled) or false (disabled)
+ * Exceptions: none
+ */
+ static jboolean isSELinuxEnabled(JNIEnv *env, jobject classz) {
+
+ return !isSELinuxDisabled;
+ }
+
+ /*
+ * Function: isSELinuxEnforced
+ * Purpose: return the current SELinux enforce mode
+ * Parameters: none
+ * Return value: true (enforcing) or false (permissive)
+ * Exceptions: none
+ */
+ static jboolean isSELinuxEnforced(JNIEnv *env, jobject clazz) {
+#ifdef HAVE_SELINUX
+ return (security_getenforce() == 1) ? true : false;
+#else
+ return false;
+#endif
+ }
+
+ /*
+ * Function: setSELinuxEnforce
+ * Purpose: set the SE Linux enforcing mode
+ * Parameters: true (enforcing) or false (permissive)
+ * Return value: true (success) or false (fail)
+ * Exceptions: none
+ */
+ static jboolean setSELinuxEnforce(JNIEnv *env, jobject clazz, jboolean value) {
+#ifdef HAVE_SELINUX
+ if (isSELinuxDisabled)
+ return false;
+
+ int enforce = (value) ? 1 : 0;
+
+ return (security_setenforce(enforce) != -1) ? true : false;
+#else
+ return false;
+#endif
+ }
+
+ /*
+ * Function: getPeerCon
+ * Purpose: retrieves security context of peer socket
+ * Parameters:
+ * fileDescriptor: peer socket file as a FileDescriptor object
+ * Returns: jstring representing the security_context of socket or NULL if error
+ * Exceptions: NullPointerException if fileDescriptor object is NULL
+ */
+ static jstring getPeerCon(JNIEnv *env, jobject clazz, jobject fileDescriptor) {
+#ifdef HAVE_SELINUX
+ if (isSELinuxDisabled)
+ return NULL;
+
+ if (fileDescriptor == NULL) {
+ throw_NullPointerException(env, "Trying to check security context of a null peer socket.");
+ return NULL;
+ }
+
+ security_context_t context = NULL;
+ jstring securityString = NULL;
+
+ int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+
+ if (env->ExceptionOccurred() != NULL) {
+ LOGE("There was an issue with retrieving the file descriptor");
+ goto bail;
+ }
+
+ if (getpeercon(fd, &context) == -1)
+ goto bail;
+
+ LOGV("getPeerCon: Successfully retrived context of peer socket '%s'", context);
+
+ securityString = env->NewStringUTF(context);
+
+ bail:
+ if (context != NULL)
+ freecon(context);
+
+ return securityString;
+#else
+ return NULL;
+#endif
+ }
+
+ /*
+ * Function: setFSCreateCon
+ * Purpose: set security context used for creating a new file system object
+ * Parameters:
+ * context: security_context_t representing the new context of a file system object,
+ * set to NULL to return to the default policy behavior
+ * Returns: true on success, false on error
+ * Exception: none
+ */
+ static jboolean setFSCreateCon(JNIEnv *env, jobject clazz, jstring context) {
+#ifdef HAVE_SELINUX
+ if (isSELinuxDisabled)
+ return false;
+
+ char * securityContext = NULL;
+ const char *constant_securityContext = NULL;
+
+ if (context != NULL) {
+ constant_securityContext = env->GetStringUTFChars(context, NULL);
+
+ // GetStringUTFChars returns const char * yet setfscreatecon needs char *
+ securityContext = const_cast<char *>(constant_securityContext);
+ }
+
+ int ret;
+ if ((ret = setfscreatecon(securityContext)) == -1)
+ goto bail;
+
+ LOGV("setFSCreateCon: set new security context to '%s' ", context == NULL ? "default", context);
+
+ bail:
+ if (constant_securityContext != NULL)
+ env->ReleaseStringUTFChars(context, constant_securityContext);
+
+ return (ret == 0) ? true : false;
+#else
+ return false;
+#endif
+ }
+
+ /*
+ * Function: setFileCon
+ * Purpose: set the security context of a file object
+ * Parameters:
+ * path: the location of the file system object
+ * con: the new security context of the file system object
+ * Returns: true on success, false on error
+ * Exception: NullPointerException is thrown if either path or context strign are NULL
+ */
+ static jboolean setFileCon(JNIEnv *env, jobject clazz, jstring path, jstring con) {
+#ifdef HAVE_SELINUX
+ if (isSELinuxDisabled)
+ return false;
+
+ if (path == NULL) {
+ throw_NullPointerException(env, "Trying to change the security context of a NULL file object.");
+ return false;
+ }
+
+ if (con == NULL) {
+ throw_NullPointerException(env, "Trying to set the security context of a file object with NULL.");
+ return false;
+ }
+
+ const char *objectPath = env->GetStringUTFChars(path, NULL);
+ const char *constant_con = env->GetStringUTFChars(con, NULL);
+
+ // GetStringUTFChars returns const char * yet setfilecon needs char *
+ char *newCon = const_cast<char *>(constant_con);
+
+ int ret;
+ if ((ret = setfilecon(objectPath, newCon)) == -1)
+ goto bail;
+
+ LOGV("setFileCon: Succesfully set security context '%s' for '%s'", newCon, objectPath);
+
+ bail:
+ env->ReleaseStringUTFChars(path, objectPath);
+ env->ReleaseStringUTFChars(con, constant_con);
+ return (ret == 0) ? true : false;
+#else
+ return false;
+#endif
+ }
+
+ /*
+ * Function: getFileCon
+ * Purpose: retrieves the context associated with the given path in the file system
+ * Parameters:
+ * path: given path in the file system
+ * Returns:
+ * string representing the security context string of the file object
+ * the string may be NULL if an error occured
+ * Exceptions: NullPointerException if the path object is null
+ */
+ static jstring getFileCon(JNIEnv *env, jobject clazz, jstring path) {
+#ifdef HAVE_SELINUX
+ if (isSELinuxDisabled)
+ return NULL;
+
+ if (path == NULL) {
+ throw_NullPointerException(env, "Trying to check security context of a null path.");
+ return NULL;
+ }
+
+ const char *objectPath = env->GetStringUTFChars(path, NULL);
+
+ security_context_t context = NULL;
+ jstring securityString = NULL;
+
+ if (getfilecon(objectPath, &context) == -1)
+ goto bail;
+
+ LOGV("getFileCon: Successfully retrived context '%s' for file '%s'", context, objectPath);
+
+ securityString = env->NewStringUTF(context);
+
+ bail:
+ if (context != NULL)
+ freecon(context);
+
+ env->ReleaseStringUTFChars(path, objectPath);
+
+ return securityString;
+#else
+ return NULL;
+#endif
+ }
+
+ /*
+ * Function: getCon
+ * Purpose: Get the context of the current process.
+ * Parameters: none
+ * Returns: a jstring representing the security context of the process,
+ * the jstring may be NULL if there was an error
+ * Exceptions: none
+ */
+ static jstring getCon(JNIEnv *env, jobject clazz) {
+#ifdef HAVE_SELINUX
+ if (isSELinuxDisabled)
+ return NULL;
+
+ security_context_t context = NULL;
+ jstring securityString = NULL;
+
+ if (getcon(&context) == -1)
+ goto bail;
+
+ LOGV("getCon: Successfully retrieved context '%s'", context);
+
+ securityString = env->NewStringUTF(context);
+
+ bail:
+ if (context != NULL)
+ freecon(context);
+
+ return securityString;
+#else
+ return NULL;
+#endif
+ }
+
+ /*
+ * Function: getPidCon
+ * Purpose: Get the context of a process identified by its pid
+ * Parameters:
+ * pid: a jint representing the process
+ * Returns: a jstring representing the security context of the pid,
+ * the jstring may be NULL if there was an error
+ * Exceptions: none
+ */
+ static jstring getPidCon(JNIEnv *env, jobject clazz, jint pid) {
+#ifdef HAVE_SELINUX
+ if (isSELinuxDisabled)
+ return NULL;
+
+ security_context_t context = NULL;
+ jstring securityString = NULL;
+
+ pid_t checkPid = (pid_t)pid;
+
+ if (getpidcon(checkPid, &context) == -1)
+ goto bail;
+
+ LOGV("getPidCon: Successfully retrived context '%s' for pid '%d'", context, checkPid);
+
+ securityString = env->NewStringUTF(context);
+
+ bail:
+ if (context != NULL)
+ freecon(context);
+
+ return securityString;
+#else
+ return NULL;
+#endif
+ }
+
+ /*
+ * Function: getBooleanNames
+ * Purpose: Gets a list of the SELinux boolean names.
+ * Parameters: None
+ * Returns: an array of strings containing the SELinux boolean names.
+ * returns NULL string on error
+ * Exceptions: None
+ */
+ static jobjectArray getBooleanNames(JNIEnv *env, JNIEnv clazz) {
+#ifdef HAVE_SELINUX
+ if (isSELinuxDisabled)
+ return NULL;
+
+ char **list;
+ int i, len, ret;
+ jclass stringClass;
+ jobjectArray stringArray = NULL;
+
+ if (security_get_boolean_names(&list, &len) == -1)
+ return NULL;
+
+ stringClass = env->FindClass("java/lang/String");
+ stringArray = env->NewObjectArray(len, stringClass, env->NewStringUTF(""));
+ for (i = 0; i < len; i++) {
+ jstring obj;
+ obj = env->NewStringUTF(list[i]);
+ env->SetObjectArrayElement(stringArray, i, obj);
+ env->DeleteLocalRef(obj);
+ free(list[i]);
+ }
+ free(list);
+
+ return stringArray;
+#else
+ return NULL;
+#endif
+ }
+
+ /*
+ * Function: getBooleanValue
+ * Purpose: Gets the value for the given SELinux boolean name.
+ * Parameters:
+ * String: The name of the SELinux boolean.
+ * Returns: a boolean: (true) boolean is set or (false) it is not.
+ * Exceptions: None
+ */
+ static jboolean getBooleanValue(JNIEnv *env, jobject clazz, jstring name) {
+#ifdef HAVE_SELINUX
+ if (isSELinuxDisabled)
+ return false;
+
+ const char *boolean_name;
+ int ret;
+
+ if (name == NULL)
+ return false;
+ boolean_name = env->GetStringUTFChars(name, NULL);
+ ret = security_get_boolean_active(boolean_name);
+ env->ReleaseStringUTFChars(name, boolean_name);
+ return (ret == 1) ? true : false;
+#else
+ return false;
+#endif
+ }
+
+ /*
+ * Function: setBooleanNames
+ * Purpose: Sets the value for the given SELinux boolean name.
+ * Parameters:
+ * String: The name of the SELinux boolean.
+ * Boolean: The new value of the SELinux boolean.
+ * Returns: a boolean indicating whether or not the operation succeeded.
+ * Exceptions: None
+ */
+ static jboolean setBooleanValue(JNIEnv *env, jobject clazz, jstring name, jboolean value) {
+#ifdef HAVE_SELINUX
+ if (isSELinuxDisabled)
+ return false;
+
+ const char *boolean_name = NULL;
+ int ret;
+
+ if (name == NULL)
+ return false;
+ boolean_name = env->GetStringUTFChars(name, NULL);
+ ret = security_set_boolean(boolean_name, (value) ? 1 : 0);
+ env->ReleaseStringUTFChars(name, boolean_name);
+ if (ret)
+ return false;
+
+ if (security_commit_booleans() == -1)
+ return false;
+
+ return true;
+#else
+ return false;
+#endif
+ }
+
+ /*
+ * Function: checkSELinuxAccess
+ * Purpose: Check permissions between two security contexts.
+ * Parameters: scon: subject security context as a string
+ * tcon: object security context as a string
+ * tclass: object's security class name as a string
+ * perm: permission name as a string
+ * Returns: boolean: (true) if permission was granted, (false) otherwise
+ * Exceptions: None
+ */
+ static jboolean checkSELinuxAccess(JNIEnv *env, jobject clazz, jstring scon, jstring tcon, jstring tclass, jstring perm) {
+#ifdef HAVE_SELINUX
+ if (isSELinuxDisabled)
+ return true;
+
+ int accessGranted = -1;
+
+ const char *const_scon, *const_tcon, *mytclass, *myperm;
+ char *myscon, *mytcon;
+
+ if (scon == NULL || tcon == NULL || tclass == NULL || perm == NULL)
+ goto bail;
+
+ const_scon = env->GetStringUTFChars(scon, NULL);
+ const_tcon = env->GetStringUTFChars(tcon, NULL);
+ mytclass = env->GetStringUTFChars(tclass, NULL);
+ myperm = env->GetStringUTFChars(perm, NULL);
+
+ // selinux_check_access needs char* for some
+ myscon = const_cast<char *>(const_scon);
+ mytcon = const_cast<char *>(const_tcon);
+
+ accessGranted = selinux_check_access(myscon, mytcon, mytclass, myperm, NULL);
+
+ LOGV("selinux_check_access returned %d", accessGranted);
+
+ env->ReleaseStringUTFChars(scon, const_scon);
+ env->ReleaseStringUTFChars(tcon, const_tcon);
+ env->ReleaseStringUTFChars(tclass, mytclass);
+ env->ReleaseStringUTFChars(perm, myperm);
+
+ bail:
+ return (accessGranted == 0) ? true : false;
+
+#else
+ return true;
+#endif
+ }
+
+ /*
+ * JNI registration.
+ */
+ static JNINativeMethod method_table[] = {
+
+ /* name, signature, funcPtr */
+ { "checkSELinuxAccess" , "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z" , (void*)checkSELinuxAccess },
+ { "getBooleanNames" , "()[Ljava/lang/String;" , (void*)getBooleanNames },
+ { "getBooleanValue" , "(Ljava/lang/String;)Z" , (void*)getBooleanValue },
+ { "getContext" , "()Ljava/lang/String;" , (void*)getCon },
+ { "getFileContext" , "(Ljava/lang/String;)Ljava/lang/String;" , (void*)getFileCon },
+ { "getPeerContext" , "(Ljava/io/FileDescriptor;)Ljava/lang/String;" , (void*)getPeerCon },
+ { "getPidContext" , "(I)Ljava/lang/String;" , (void*)getPidCon },
+ { "isSELinuxEnforced" , "()Z" , (void*)isSELinuxEnforced},
+ { "isSELinuxEnabled" , "()Z" , (void*)isSELinuxEnabled },
+ { "setBooleanValue" , "(Ljava/lang/String;Z)Z" , (void*)setBooleanValue },
+ { "setFileContext" , "(Ljava/lang/String;Ljava/lang/String;)Z" , (void*)setFileCon },
+ { "setFSCreateContext" , "(Ljava/lang/String;)Z" , (void*)setFSCreateCon },
+ { "setSELinuxEnforce" , "(Z)Z" , (void*)setSELinuxEnforce},
+ };
+
+ static int log_callback(int type, const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ LOG_PRI_VA(ANDROID_LOG_ERROR, "SELinux", fmt, ap);
+ va_end(ap);
+ return 0;
+ }
+
+ int register_android_os_SELinux(JNIEnv *env) {
+#ifdef HAVE_SELINUX
+ union selinux_callback cb;
+ cb.func_log = log_callback;
+ selinux_set_callback(SELINUX_CB_LOG, cb);
+
+ isSELinuxDisabled = (is_selinux_enabled() != 1) ? true : false;
+
+#endif
+ return AndroidRuntime::registerNativeMethods(
+ env, "android/os/SELinux",
+ method_table, NELEM(method_table));
+ }
+}
diff --git a/core/res/res/layout/transient_notification.xml b/core/res/res/layout/transient_notification.xml
index 21d58aa..5523807 100644
--- a/core/res/res/layout/transient_notification.xml
+++ b/core/res/res/layout/transient_notification.xml
@@ -29,6 +29,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
+ android:layout_gravity="center_horizontal"
android:textAppearance="@style/TextAppearance.Small"
android:textColor="@color/bright_foreground_dark"
android:shadowColor="#BB000000"
diff --git a/core/tests/coretests/apks/install_complete_package_info/Android.mk b/core/tests/coretests/apks/install_complete_package_info/Android.mk
new file mode 100644
index 0000000..1edccb4
--- /dev/null
+++ b/core/tests/coretests/apks/install_complete_package_info/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := FrameworkCoreTests_install_complete_package_info
+
+include $(BUILD_PACKAGE)
+
diff --git a/core/tests/coretests/apks/install_complete_package_info/AndroidManifest.xml b/core/tests/coretests/apks/install_complete_package_info/AndroidManifest.xml
new file mode 100644
index 0000000..4b01736
--- /dev/null
+++ b/core/tests/coretests/apks/install_complete_package_info/AndroidManifest.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.coretests.install_complete_package_info">
+
+<!--
+ This manifest declares at least one of each of the components that
+ can be retrieved by PackageManager.getInstalledPackages.
+ All the implementing classes are empty implementations
+-->
+
+ <uses-feature
+ android:name="com.android.frameworks.coretests.nonexistent" />
+ <uses-configuration
+ android:reqFiveWayNav="false" />
+
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.frameworks.coretests"
+ android:label="Frameworks Core Tests" />
+
+ <permission
+ android:label="test permission"
+ android:name="test_permission"
+ android:protectionLevel="normal" />
+
+ <application
+ android:hasCode="true">
+ <activity
+ android:name="com.android.frameworks.coretests.TestActivity">
+ </activity>
+ <provider
+ android:name="com.android.frameworks.coretests.TestProvider"
+ android:authorities="com.android.frameworks.coretests.testprovider" />
+ <receiver
+ android:name="com.android.frameworks.coretests.TestReceiver" />
+ <service
+ android:name="com.android.frameworks.coretests.TestService" />
+ </application>
+</manifest>
diff --git a/core/tests/coretests/apks/install_complete_package_info/src/com/android/frameworks/coretests/TestActivity.java b/core/tests/coretests/apks/install_complete_package_info/src/com/android/frameworks/coretests/TestActivity.java
new file mode 100644
index 0000000..10d0551
--- /dev/null
+++ b/core/tests/coretests/apks/install_complete_package_info/src/com/android/frameworks/coretests/TestActivity.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2011 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.frameworks.coretests;
+
+import android.app.Activity;
+
+public class TestActivity extends Activity {
+
+}
diff --git a/core/tests/coretests/apks/install_complete_package_info/src/com/android/frameworks/coretests/TestProvider.java b/core/tests/coretests/apks/install_complete_package_info/src/com/android/frameworks/coretests/TestProvider.java
new file mode 100644
index 0000000..59f9f10
--- /dev/null
+++ b/core/tests/coretests/apks/install_complete_package_info/src/com/android/frameworks/coretests/TestProvider.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 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.frameworks.coretests;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+
+public class TestProvider extends ContentProvider {
+
+ @Override
+ public boolean onCreate() {
+ return false;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ return null;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ return 0;
+ }
+}
diff --git a/core/tests/coretests/apks/install_complete_package_info/src/com/android/frameworks/coretests/TestReceiver.java b/core/tests/coretests/apks/install_complete_package_info/src/com/android/frameworks/coretests/TestReceiver.java
new file mode 100644
index 0000000..21f6263
--- /dev/null
+++ b/core/tests/coretests/apks/install_complete_package_info/src/com/android/frameworks/coretests/TestReceiver.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 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.frameworks.coretests;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+
+public class TestReceiver extends ContentProvider {
+
+ @Override
+ public boolean onCreate() {
+ return false;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ return null;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ return 0;
+ }
+}
diff --git a/core/tests/coretests/apks/install_complete_package_info/src/com/android/frameworks/coretests/TestService.java b/core/tests/coretests/apks/install_complete_package_info/src/com/android/frameworks/coretests/TestService.java
new file mode 100644
index 0000000..b330e75
--- /dev/null
+++ b/core/tests/coretests/apks/install_complete_package_info/src/com/android/frameworks/coretests/TestService.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011 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.frameworks.coretests;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class TestService extends Service {
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+}
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 77e4986..6e1b9d6 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -23,6 +23,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
@@ -50,6 +51,8 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.util.List;
+
public class PackageManagerTests extends AndroidTestCase {
private static final boolean localLOGV = true;
public static final String TAG="PackageManagerTests";
@@ -3162,6 +3165,92 @@ public class PackageManagerTests extends AndroidTestCase {
assertNotNull("Verifier device identity should not be null", id);
}
+ public void testGetInstalledPackages() {
+ List<PackageInfo> packages = getPm().getInstalledPackages(0);
+ assertNotNull("installed packages cannot be null", packages);
+ assertTrue("installed packages cannot be empty", packages.size() > 0);
+ }
+
+ public void testGetUnInstalledPackages() {
+ List<PackageInfo> packages = getPm().getInstalledPackages(
+ PackageManager.GET_UNINSTALLED_PACKAGES);
+ assertNotNull("installed packages cannot be null", packages);
+ assertTrue("installed packages cannot be empty", packages.size() > 0);
+ }
+
+ /**
+ * Test that getInstalledPackages returns all the data specified in
+ * flags.
+ */
+ public void testGetInstalledPackagesAll() {
+ int flags = PackageManager.GET_ACTIVITIES | PackageManager.GET_GIDS
+ | PackageManager.GET_CONFIGURATIONS | PackageManager.GET_INSTRUMENTATION
+ | PackageManager.GET_PERMISSIONS | PackageManager.GET_PROVIDERS
+ | PackageManager.GET_RECEIVERS | PackageManager.GET_SERVICES
+ | PackageManager.GET_SIGNATURES | PackageManager.GET_UNINSTALLED_PACKAGES;
+
+ List<PackageInfo> packages = getPm().getInstalledPackages(flags);
+ assertNotNull("installed packages cannot be null", packages);
+ assertTrue("installed packages cannot be empty", packages.size() > 0);
+
+ PackageInfo packageInfo = null;
+
+ // Find the package with all components specified in the AndroidManifest
+ // to ensure no null values
+ for (PackageInfo pi : packages) {
+ if ("com.android.frameworks.coretests.install_complete_package_info"
+ .equals(pi.packageName)) {
+ packageInfo = pi;
+ break;
+ }
+ }
+ assertNotNull("activities should not be null", packageInfo.activities);
+ assertNotNull("configPreferences should not be null", packageInfo.configPreferences);
+ assertNotNull("instrumentation should not be null", packageInfo.instrumentation);
+ assertNotNull("permissions should not be null", packageInfo.permissions);
+ assertNotNull("providers should not be null", packageInfo.providers);
+ assertNotNull("receivers should not be null", packageInfo.receivers);
+ assertNotNull("services should not be null", packageInfo.services);
+ assertNotNull("signatures should not be null", packageInfo.signatures);
+ }
+
+ /**
+ * Test that getInstalledPackages returns all the data specified in
+ * flags when the GET_UNINSTALLED_PACKAGES flag is set.
+ */
+ public void testGetUnInstalledPackagesAll() {
+ int flags = PackageManager.GET_UNINSTALLED_PACKAGES
+ | PackageManager.GET_ACTIVITIES | PackageManager.GET_GIDS
+ | PackageManager.GET_CONFIGURATIONS | PackageManager.GET_INSTRUMENTATION
+ | PackageManager.GET_PERMISSIONS | PackageManager.GET_PROVIDERS
+ | PackageManager.GET_RECEIVERS | PackageManager.GET_SERVICES
+ | PackageManager.GET_SIGNATURES | PackageManager.GET_UNINSTALLED_PACKAGES;
+
+ List<PackageInfo> packages = getPm().getInstalledPackages(flags);
+ assertNotNull("installed packages cannot be null", packages);
+ assertTrue("installed packages cannot be empty", packages.size() > 0);
+
+ PackageInfo packageInfo = null;
+
+ // Find the package with all components specified in the AndroidManifest
+ // to ensure no null values
+ for (PackageInfo pi : packages) {
+ if ("com.android.frameworks.coretests.install_complete_package_info"
+ .equals(pi.packageName)) {
+ packageInfo = pi;
+ break;
+ }
+ }
+ assertNotNull("activities should not be null", packageInfo.activities);
+ assertNotNull("configPreferences should not be null", packageInfo.configPreferences);
+ assertNotNull("instrumentation should not be null", packageInfo.instrumentation);
+ assertNotNull("permissions should not be null", packageInfo.permissions);
+ assertNotNull("providers should not be null", packageInfo.providers);
+ assertNotNull("receivers should not be null", packageInfo.receivers);
+ assertNotNull("services should not be null", packageInfo.services);
+ assertNotNull("signatures should not be null", packageInfo.signatures);
+ }
+
/*---------- Recommended install location tests ----*/
/*
* TODO's
diff --git a/core/tests/coretests/src/android/os/SELinuxTest.java b/core/tests/coretests/src/android/os/SELinuxTest.java
new file mode 100644
index 0000000..9b63a6b
--- /dev/null
+++ b/core/tests/coretests/src/android/os/SELinuxTest.java
@@ -0,0 +1,45 @@
+package android.os;
+
+import android.os.Process;
+import android.os.SELinux;
+import android.test.AndroidTestCase;
+import static junit.framework.Assert.assertEquals;
+
+public class SELinuxTest extends AndroidTestCase {
+
+ public void testgetFileCon() {
+ if(SELinux.isSELinuxEnabled() == false)
+ return;
+
+ String ctx = SELinux.getFileContext("/system/bin/toolbox");
+ assertEquals(ctx, "u:object_r:system_file:s0");
+ }
+
+ public void testgetCon() {
+ if(SELinux.isSELinuxEnabled() == false)
+ return;
+
+ String mycon = SELinux.getContext();
+ assertEquals(mycon, "u:r:untrusted_app:s0:c33");
+ }
+
+ public void testgetPidCon() {
+ if(SELinux.isSELinuxEnabled() == false)
+ return;
+
+ String mycon = SELinux.getPidContext(Process.myPid());
+ assertEquals(mycon, "u:r:untrusted_app:s0:c33");
+ }
+
+ public void testcheckSELinuxAccess() {
+ if(SELinux.isSELinuxEnabled() == false)
+ return;
+
+ String mycon = SELinux.getContext();
+ boolean ret;
+ ret = SELinux.checkSELinuxAccess(mycon, mycon, "process", "fork");
+ assertEquals(ret,"true");
+ ret = SELinux.checkSELinuxAccess(mycon, mycon, "memprotect", "mmap_zero");
+ assertEquals(ret,"true");
+ }
+}
diff --git a/core/tests/overlaytests/OverlayTestOverlay/Android.mk b/core/tests/overlaytests/OverlayTestOverlay/Android.mk
index cf32c9f..b1327f7 100644
--- a/core/tests/overlaytests/OverlayTestOverlay/Android.mk
+++ b/core/tests/overlaytests/OverlayTestOverlay/Android.mk
@@ -9,6 +9,4 @@ LOCAL_SDK_VERSION := current
LOCAL_PACKAGE_NAME := com.android.overlaytest.overlay
-LOCAL_AAPT_FLAGS := -o
-
include $(BUILD_PACKAGE)
diff --git a/core/tests/overlaytests/OverlayTestOverlay/res/drawable/default_wallpaper.jpg b/core/tests/overlaytests/OverlayTestOverlay/res/drawable-nodpi/default_wallpaper.jpg
index 0d944d0..0d944d0 100644
--- a/core/tests/overlaytests/OverlayTestOverlay/res/drawable/default_wallpaper.jpg
+++ b/core/tests/overlaytests/OverlayTestOverlay/res/drawable-nodpi/default_wallpaper.jpg
Binary files differ
diff --git a/core/tests/overlaytests/runtests.sh b/core/tests/overlaytests/runtests.sh
index 0ad9efb..0a721ad40 100755
--- a/core/tests/overlaytests/runtests.sh
+++ b/core/tests/overlaytests/runtests.sh
@@ -18,7 +18,6 @@ function atexit()
log=$(mktemp)
trap "atexit" EXIT
-failures=0
function compile_module()
{
@@ -38,6 +37,37 @@ function wait_for_boot_completed()
$adb wait-for-device logcat | grep -m 1 -e 'PowerManagerService.*bootCompleted' >/dev/null
}
+function mkdir_if_needed()
+{
+ local path="$1"
+
+ if [[ "${path:0:1}" != "/" ]]; then
+ echo "mkdir_if_needed: error: path '$path' does not begin with /" | tee -a $log
+ exit 1
+ fi
+
+ local basename=$(basename "$path")
+ local dirname=$(dirname "$path")
+ local t=$($adb shell ls -l $dirname | tr -d '\r' | grep -e "${basename}$" | grep -oe '^.')
+
+ case "$t" in
+ d) # File exists, and is a directory ...
+ # do nothing
+ ;;
+ l) # ... (or symbolic link possibly to a directory).
+ # do nothing
+ ;;
+ "") # File does not exist.
+ mkdir_if_needed "$dirname"
+ $adb shell mkdir "$path"
+ ;;
+ *) # File exists, but is not a directory.
+ echo "mkdir_if_needed: file '$path' exists, but is not a directory" | tee -a $log
+ exit 1
+ ;;
+ esac
+}
+
function disable_overlay()
{
echo "Disabling overlay"
@@ -48,6 +78,8 @@ function disable_overlay()
function enable_overlay()
{
echo "Enabling overlay"
+ mkdir_if_needed "/system/vendor"
+ mkdir_if_needed "/vendor/overlay/framework"
$adb shell ln -s /data/app/com.android.overlaytest.overlay.apk /vendor/overlay/framework/framework-res.apk
}
@@ -59,13 +91,21 @@ function instrument()
$adb shell am instrument -w -e class $class com.android.overlaytest/android.test.InstrumentationTestRunner | tee -a $log
}
+function remount()
+{
+ echo "Remounting file system writable"
+ $adb remount | tee -a $log
+}
+
function sync()
{
echo "Syncing to device"
- $adb remount | tee -a $log
$adb sync data | tee -a $log
}
+# some commands require write access, remount once and for all
+remount
+
# build and sync
compile_module "$PWD/OverlayTest/Android.mk"
compile_module "$PWD/OverlayTestOverlay/Android.mk"