blob: 99481fc25706f49b360a64709568c38fa44d745e [file] [log] [blame]
// Copyright (C) 2016 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 apk provides methods to get information (e.g. manifests, ABIs)
// from APKs, as well as taking an APK and making it debuggable, for testing
// purposes.
package apk
import (
"archive/zip"
"bytes"
"io/ioutil"
"strings"
"android.googlesource.com/platform/tools/gpu/client/android/binaryxml"
"android.googlesource.com/platform/tools/gpu/client/android/manifest"
"android.googlesource.com/platform/tools/gpu/framework/device"
"android.googlesource.com/platform/tools/gpu/framework/log"
)
const mainfestPath = "AndroidManifest.xml"
// Read parses the APK file, returning its contents.
func Read(ctx log.Context, apkData []byte) ([]*zip.File, error) {
apkZip, err := zip.NewReader(bytes.NewReader(apkData), int64(len(apkData)))
if err != nil {
return nil, ctx.AsError("File is not an APK.")
}
return apkZip.File, nil
}
func GetManifestXML(ctx log.Context, files []*zip.File) (string, error) {
manifestZipFile := findManifest(files)
if manifestZipFile == nil {
return "", ctx.AsError("Couldn't find APK's manifest file.")
}
manifestFile, err := manifestZipFile.Open()
if err != nil {
return "", ctx.WrapError(err, "Couldn't open APK's manifest")
}
defer manifestFile.Close()
manifestData, _ := ioutil.ReadAll(manifestFile)
return binaryxml.Decode(ctx, manifestData)
}
func GetManifest(ctx log.Context, files []*zip.File) (manifest.Manifest, error) {
manifestXML, err := GetManifestXML(ctx, files)
if err != nil {
return manifest.Manifest{}, err
}
return manifest.Parse(ctx, manifestXML)
}
func findManifest(files []*zip.File) *zip.File {
for _, file := range files {
if file.Name == mainfestPath {
return file
}
}
return nil
}
func GatherABIs(files []*zip.File) []*device.ABI {
abis := []*device.ABI{}
seen := map[string]struct{}{}
for _, f := range files {
parts := strings.Split(f.Name, "/")
if len(parts) >= 2 && parts[0] == "lib" {
abiName := parts[1]
if _, existing := seen[abiName]; !existing {
abi := device.ABIByName(abiName)
abis = append(abis, &abi)
seen[abiName] = struct{}{}
}
}
}
return abis
}