Merge "Add OBB flags to support overlays" into gingerbread
diff --git a/core/java/android/content/res/ObbInfo.java b/core/java/android/content/res/ObbInfo.java
index b18d784..838c5ff 100644
--- a/core/java/android/content/res/ObbInfo.java
+++ b/core/java/android/content/res/ObbInfo.java
@@ -25,6 +25,9 @@
  * @hide
  */
 public class ObbInfo implements Parcelable {
+    /** Flag noting that this OBB is an overlay patch for a base OBB. */
+    public static final int OBB_OVERLAY = 1 << 0;
+
     /**
      * The name of the package to which the OBB file belongs.
      */
@@ -35,13 +38,26 @@
      */
     public int version;
 
+    /**
+     * The flags relating to the OBB.
+     */
+    public int flags;
+
     public ObbInfo() {
     }
 
     public String toString() {
-        return "ObbInfo{"
-            + Integer.toHexString(System.identityHashCode(this))
-            + " packageName=" + packageName + ",version=" + version + "}";
+        StringBuilder sb = new StringBuilder();
+        sb.append("ObbInfo{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(" packageName=");
+        sb.append(packageName);
+        sb.append(",version=");
+        sb.append(version);
+        sb.append(",flags=");
+        sb.append(flags);
+        sb.append('}');
+        return sb.toString();
     }
 
     public int describeContents() {
@@ -51,6 +67,7 @@
     public void writeToParcel(Parcel dest, int parcelableFlags) {
         dest.writeString(packageName);
         dest.writeInt(version);
+        dest.writeInt(flags);
     }
 
     public static final Parcelable.Creator<ObbInfo> CREATOR
@@ -67,5 +84,6 @@
     private ObbInfo(Parcel source) {
         packageName = source.readString();
         version = source.readInt();
+        flags = source.readInt();
     }
 }
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index cb1794f..df0b69c 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -304,6 +304,8 @@
      * file matches a package ID that is owned by the calling program's UID.
      * That is, shared UID applications can obtain access to any other
      * application's OBB that shares its UID.
+     * <p>
+     * STOPSHIP document more; discuss lack of guarantees of security
      * 
      * @param filename the path to the OBB file
      * @param key decryption key
@@ -328,6 +330,8 @@
      * file matches a package ID that is owned by the calling program's UID.
      * That is, shared UID applications can obtain access to any other
      * application's OBB that shares its UID.
+     * <p>
+     * STOPSHIP document more; discuss lack of guarantees of security
      * 
      * @param filename path to the OBB file
      * @param force whether to kill any programs using this in order to unmount
diff --git a/core/jni/android_content_res_ObbScanner.cpp b/core/jni/android_content_res_ObbScanner.cpp
index 1239274..62c89fc 100644
--- a/core/jni/android_content_res_ObbScanner.cpp
+++ b/core/jni/android_content_res_ObbScanner.cpp
@@ -31,6 +31,7 @@
 
     jfieldID packageName;
     jfieldID version;
+    jfieldID flags;
 } gObbInfoClassInfo;
 
 static jboolean android_content_res_ObbScanner_getObbInfo(JNIEnv* env, jobject clazz, jstring file,
@@ -85,6 +86,8 @@
             "packageName", "Ljava/lang/String;");
     GET_FIELD_ID(gObbInfoClassInfo.version, gObbInfoClassInfo.clazz,
             "version", "I");
+    GET_FIELD_ID(gObbInfoClassInfo.flags, gObbInfoClassInfo.clazz,
+            "flags", "I");
 
     return AndroidRuntime::registerNativeMethods(env, "android/content/res/ObbScanner", gMethods,
             NELEM(gMethods));
diff --git a/include/utils/ObbFile.h b/include/utils/ObbFile.h
index d2ca82e..5243f50 100644
--- a/include/utils/ObbFile.h
+++ b/include/utils/ObbFile.h
@@ -18,12 +18,16 @@
 #define OBBFILE_H_
 
 #include <stdint.h>
+#include <strings.h>
 
 #include <utils/RefBase.h>
 #include <utils/String8.h>
 
 namespace android {
 
+// OBB flags (bit 0)
+#define OBB_OVERLAY         (1 << 0)
+
 class ObbFile : public RefBase {
 protected:
     virtual ~ObbFile();
@@ -46,18 +50,38 @@
         return mPackageName;
     }
 
-    int32_t getVersion() const {
-        return mVersion;
-    }
-
     void setPackageName(String8 packageName) {
         mPackageName = packageName;
     }
 
+    int32_t getVersion() const {
+        return mVersion;
+    }
+
     void setVersion(int32_t version) {
         mVersion = version;
     }
 
+    int32_t getFlags() const {
+        return mFlags;
+    }
+
+    void setFlags(int32_t flags) {
+        mFlags = flags;
+    }
+
+    bool isOverlay() {
+        return (mFlags & OBB_OVERLAY) == OBB_OVERLAY;
+    }
+
+    void setOverlay(bool overlay) {
+        if (overlay) {
+            mFlags |= OBB_OVERLAY;
+        } else {
+            mFlags &= ~OBB_OVERLAY;
+        }
+    }
+
     static inline uint32_t get4LE(const unsigned char* buf) {
         return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
     }
@@ -76,6 +100,9 @@
     /* Package version this ObbFile is associated with */
     int32_t mVersion;
 
+    /* Flags for this OBB type. */
+    int32_t mFlags;
+
     const char* mFileName;
 
     size_t mFileSize;
diff --git a/libs/utils/ObbFile.cpp b/libs/utils/ObbFile.cpp
index adedf0c..e170ab8 100644
--- a/libs/utils/ObbFile.cpp
+++ b/libs/utils/ObbFile.cpp
@@ -29,12 +29,13 @@
 
 #define kFooterTagSize 8  /* last two 32-bit integers */
 
-#define kFooterMinSize 21 /* 32-bit signature version
-                           * 32-bit package version
-                           * 32-bit package name size
-                           * 1-character package name
-                           * 32-bit footer size
-                           * 32-bit footer marker
+#define kFooterMinSize 25 /* 32-bit signature version (4 bytes)
+                           * 32-bit package version (4 bytes)
+                           * 32-bit flags (4 bytes)
+                           * 32-bit package name size (4-bytes)
+                           * >=1-character package name (1 byte)
+                           * 32-bit footer size (4 bytes)
+                           * 32-bit footer marker (4 bytes)
                            */
 
 #define kMaxBufSize    32768 /* Maximum file read buffer */
@@ -45,8 +46,9 @@
 
 /* offsets in version 1 of the header */
 #define kPackageVersionOffset 4
-#define kPackageNameLenOffset 8
-#define kPackageNameOffset    12
+#define kFlagsOffset          8
+#define kPackageNameLenOffset 12
+#define kPackageNameOffset    16
 
 /*
  * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
@@ -78,7 +80,10 @@
 namespace android {
 
 ObbFile::ObbFile() :
-        mVersion(-1) {
+        mPackageName(""),
+        mVersion(-1),
+        mFlags(0)
+{
 }
 
 ObbFile::~ObbFile() {
@@ -199,6 +204,7 @@
     }
 
     mVersion = (int32_t) get4LE((unsigned char*)scanBuf + kPackageVersionOffset);
+    mFlags = (int32_t) get4LE((unsigned char*)scanBuf + kFlagsOffset);
 
     uint32_t packageNameLen = get4LE((unsigned char*)scanBuf + kPackageNameLenOffset);
     if (packageNameLen <= 0
@@ -268,6 +274,12 @@
         return false;
     }
 
+    put4LE(intBuf, mFlags);
+    if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
+        LOGW("couldn't write package version");
+        return false;
+    }
+
     size_t packageNameLen = mPackageName.size();
     put4LE(intBuf, packageNameLen);
     if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
@@ -280,7 +292,7 @@
         return false;
     }
 
-    put4LE(intBuf, 3*sizeof(uint32_t) + packageNameLen);
+    put4LE(intBuf, kPackageNameOffset + packageNameLen);
     if (write(fd, &intBuf, sizeof(uint32_t)) != (ssize_t)sizeof(uint32_t)) {
         LOGW("couldn't write footer size: %s", strerror(errno));
         return false;
diff --git a/tools/obbtool/Main.cpp b/tools/obbtool/Main.cpp
index 2a9bf04..49e077f 100644
--- a/tools/obbtool/Main.cpp
+++ b/tools/obbtool/Main.cpp
@@ -29,7 +29,7 @@
 static int wantUsage = 0;
 static int wantVersion = 0;
 
-#define ADD_OPTS "n:v:f:c:"
+#define ADD_OPTS "n:v:o"
 static const struct option longopts[] = {
     {"help",       no_argument, &wantUsage,   1},
     {"version",    no_argument, &wantVersion, 1},
@@ -37,8 +37,7 @@
     /* Args for "add" */
     {"name",       required_argument, NULL, 'n'},
     {"version",    required_argument, NULL, 'v'},
-    {"filesystem", required_argument, NULL, 'f'},
-    {"crypto",     required_argument, NULL, 'c'},
+    {"overlay",    optional_argument, NULL, 'o'},
 
     {NULL, 0, NULL, '\0'}
 };
@@ -46,8 +45,7 @@
 struct package_info_t {
     char* packageName;
     int packageVersion;
-    char* filesystem;
-    char* crypto;
+    bool overlay;
 };
 
 /*
@@ -77,6 +75,7 @@
 
     obb->setPackageName(String8(info->packageName));
     obb->setVersion(info->packageVersion);
+    obb->setOverlay(info->overlay);
 
     if (!obb->writeTo(filename)) {
         fprintf(stderr, "ERROR: %s: couldn't write OBB signature: %s\n",
@@ -112,6 +111,8 @@
     printf("OBB info for '%s':\n", filename);
     printf("Package name: %s\n", obb->getPackageName().string());
     printf("     Version: %d\n", obb->getVersion());
+    printf("       Flags: 0x%08x\n", obb->getFlags());
+    printf("     Overlay: %s\n", obb->isOverlay() ? "true" : "false");
 }
 
 /*
@@ -143,7 +144,7 @@
         case 'n':
             package_info.packageName = optarg;
             break;
-        case 'v':
+        case 'v': {
             char *end;
             package_info.packageVersion = strtol(optarg, &end, 10);
             if (*optarg == '\0' || *end != '\0') {
@@ -152,11 +153,9 @@
                 goto bail;
             }
             break;
-        case 'f':
-            package_info.filesystem = optarg;
-            break;
-        case 'c':
-            package_info.crypto = optarg;
+        }
+        case 'o':
+            package_info.overlay = true;
             break;
         case '?':
             wantUsage = 1;