cmd/gomobile: support manifest screenOrientation

Testing BinaryXML for the change was non-trivial as the first 4 bytes
of gomobile output did not match the latest version of aapt's output.
A new approach to testing compatibility was added based on how the
aapt tool pretty prints xmltree of manifest's contents.

Fixes golang/go#10943

Change-Id: I5c60af10931d9693dbeaff66f23a69042a78e8fa
Reviewed-on: https://go-review.googlesource.com/16150
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
Daniel Skinner 2015-10-21 03:12:09 -05:00 коммит произвёл Hyang-Ah Hana Kim
Родитель 1b12574c99
Коммит 103b3cfae8
2 изменённых файлов: 109 добавлений и 25 удалений

Просмотреть файл

@ -237,16 +237,17 @@ func appendHeader(b []byte, typ headerType, size int) []byte {
//
// http://developer.android.com/reference/android/R.attr.html
var resourceCodes = map[string]uint32{
"versionCode": 0x0101021b,
"versionName": 0x0101021c,
"minSdkVersion": 0x0101020c,
"windowFullscreen": 0x0101020d,
"label": 0x01010001,
"hasCode": 0x0101000c,
"debuggable": 0x0101000f,
"name": 0x01010003,
"configChanges": 0x0101001f,
"value": 0x01010024,
"versionCode": 0x0101021b,
"versionName": 0x0101021c,
"minSdkVersion": 0x0101020c,
"windowFullscreen": 0x0101020d,
"label": 0x01010001,
"hasCode": 0x0101000c,
"debuggable": 0x0101000f,
"name": 0x01010003,
"screenOrientation": 0x0101001e,
"configChanges": 0x0101001f,
"value": 0x01010024,
}
// http://developer.android.com/reference/android/R.attr.html#configChanges
@ -267,6 +268,26 @@ var configChanges = map[string]uint32{
"fontScale": 0x40000000,
}
// http://developer.android.com/reference/android/R.attr.html#screenOrientation
var screenOrientation = map[string]int{
"unspecified": -1,
"landscape": 0,
"portrait": 1,
"user": 2,
"behind": 3,
"sensor": 4,
"nosensor": 5,
"sensorLandscape": 6,
"sensorPortrait": 7,
"reverseLandscape": 8,
"reversePortrait": 9,
"fullSensor": 10,
"userLandscape": 11,
"userPortrait": 12,
"fullUser": 13,
"locked": 14,
}
type lineReader struct {
off int64
lines []int64
@ -400,6 +421,12 @@ func (p *binStringPool) getAttr(attr xml.Attr) (*binAttr, error) {
v |= configChanges[c]
}
a.data = v
case "screenOrientation":
v := 0
for _, c := range strings.Split(attr.Value, "|") {
v |= screenOrientation[c]
}
a.data = v
default:
a.data = p.get(attr.Value)
}

Просмотреть файл

@ -5,10 +5,14 @@
package main
import (
"archive/zip"
"bytes"
"flag"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"testing"
)
@ -23,33 +27,83 @@ func TestBinaryXML(t *testing.T) {
sortPool, sortAttr = sortToMatchTest, sortAttrToMatchTest
defer func() { sortPool, sortAttr = origSortPool, origSortAttr }()
got, err := binaryXML(bytes.NewBufferString(input))
bin, err := binaryXML(bytes.NewBufferString(input))
if err != nil {
t.Fatal(err)
}
if *dump {
if err := ioutil.WriteFile("junk.bin", got, 0660); err != nil {
if err := ioutil.WriteFile("junk.bin", bin, 0660); err != nil {
t.Fatal(err)
}
}
skipByte := map[int]bool{
0x04ec: true, // line number of fake </uses-sdk> off by one
0x0610: true, // line number of fake </meta-data> off by one
0x064c: true, // line number of CData off by one
0x06a0: true, // line number of fake </action> off by one
0x06f0: true, // line number of fake </category> off by one
0x0768: true, // line number of fake *end namespace* off by one
if exec.Command("which", "aapt").Run() != nil {
t.Skip("command aapt not found, skipping")
}
for i, o := range output {
if skipByte[i] {
apiPath, err := androidAPIPath()
if err != nil {
t.Fatal(err)
}
androidJar := filepath.Join(apiPath, "android.jar")
tmpdir, err := ioutil.TempDir("", "gomobile-test-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
buf := new(bytes.Buffer)
zw := zip.NewWriter(buf)
zf, err := zw.Create("AndroidManifest.xml")
if err != nil {
t.Fatal(err)
}
if _, err := zf.Write(bin); err != nil {
t.Fatal(err)
}
if err := zw.Close(); err != nil {
t.Fatal(err)
}
mblapk := filepath.Join(tmpdir, "mbl.apk")
if err := ioutil.WriteFile(mblapk, buf.Bytes(), 0755); err != nil {
t.Fatal(err)
}
got, err := exec.Command("aapt", "d", "xmltree", mblapk, "AndroidManifest.xml").Output()
if err != nil {
t.Fatal(err)
}
manifest := filepath.Join(tmpdir, "AndroidManifest.xml")
if err := ioutil.WriteFile(manifest, []byte(input), 0755); err != nil {
t.Fatal(err)
}
sdkapk := filepath.Join(tmpdir, "sdk.apk")
if _, err := exec.Command("aapt", "p", "-M", manifest, "-I", androidJar, "-F", sdkapk).Output(); err != nil {
t.Fatal(err)
}
sdkout, err := exec.Command("aapt", "d", "xmltree", sdkapk, "AndroidManifest.xml").Output()
if err != nil {
t.Fatal(err)
}
// manifests contain platformBuildVersionCode and platformBuildVersionName
// which are not present in gomobile output.
var fo [][]byte
for _, line := range bytes.Split(sdkout, []byte{'\n'}) {
if bytes.Contains(line, []byte("platformBuildVersionCode")) || bytes.Contains(line, []byte("platformBuildVersionName")) {
continue
}
if i >= len(got) || o != got[i] {
t.Errorf("mismatch at %04x", i)
break
}
fo = append(fo, line)
}
want := bytes.Join(fo, []byte{'\n'})
if !bytes.Equal(want, got) {
t.Fatalf("output does not match\n\n%s\n\n%s\n", want, got)
}
}
@ -64,6 +118,7 @@ func sortToMatchTest(p *binStringPool) {
"hasCode",
"debuggable",
"name",
"screenOrientation",
"configChanges",
"value",
"android",
@ -122,6 +177,7 @@ func sortAttrToMatchTest(e *binStartElement, p *binStringPool) {
"label",
"name",
"screenOrientation",
"configChanges",
}
ordered := make([]*binAttr, len(order))
@ -744,6 +800,7 @@ license that can be found in the LICENSE file.
<application android:label="Balloon世界" android:hasCode="false" android:debuggable="true">
<activity android:name="android.app.NativeActivity"
android:label="Balloon"
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden">
<meta-data android:name="android.app.lib_name" android:value="balloon" />
<intent-filter>