From c511c88854c1e2df53b43ddb778741fead8f9363 Mon Sep 17 00:00:00 2001 From: relan Date: Mon, 18 Apr 2016 22:40:15 +0300 Subject: [PATCH] Introduce APKs suggestions Suggested APK must be compatible with a particular device. This is always one of the set of suggested APKs. This set contains APKs with the same version string but different version codes (flavours of the same version, e.g. targeting different hardware architectures). --- index.go | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/index.go b/index.go index 6853c59..101cf49 100644 --- a/index.go +++ b/index.go @@ -9,6 +9,8 @@ import ( "io" "sort" "strings" + + "github.com/mvdan/adb" ) type Index struct { @@ -209,6 +211,29 @@ func (a *Apk) SrcURL() string { return fmt.Sprintf("%s/%s", a.Repo.URL, a.SrcName) } +func (apk *Apk) IsCompatibleABI(ABIs []string) bool { + if len(apk.ABIs) == 0 { + return true // APK does not contain native code + } + for i := range apk.ABIs { + for j := range ABIs { + if apk.ABIs[i] == ABIs[j] { + return true + } + } + } + return false +} + +func (apk *Apk) IsCompatibleAPILevel(sdk int) bool { + return sdk >= apk.MinSdk && (apk.MaxSdk == 0 || sdk <= apk.MaxSdk) +} + +func (apk *Apk) IsCompatible(device *adb.Device) bool { + return apk.IsCompatibleABI(device.ABIs) && + apk.IsCompatibleAPILevel(device.APILevel) +} + type AppList []App func (al AppList) Len() int { return len(al) } @@ -254,3 +279,57 @@ func (a *App) CurApk() *Apk { } return nil } + +func (a *App) ApksByVName(vname string) []Apk { + var apks []Apk + for i := range a.Apks { + if vname == a.Apks[i].VName { + apks = append(apks, a.Apks[i]) + } + } + return apks +} + +func (a *App) SuggestedVName() string { + for i := range a.Apks { + apk := &a.Apks[i] + if a.CVCode >= apk.VCode { + return apk.VName + } + } + return "" +} + +func (a *App) SuggestedApks() []Apk { + // No APKs => nothing to suggest + if len(a.Apks) == 0 { + return nil + } + + // First, try to follow CV + apks := a.ApksByVName(a.SuggestedVName()) + if len(apks) > 0 { + return apks + } + + // When CV is missing current version code or it's invalid (no APKs + // match it), use heuristic: find all APKs having the same version + // string as the APK with the greatest version code + return a.ApksByVName(a.Apks[0].VName) +} + +func (a *App) SuggestedApk(device *adb.Device) *Apk { + for i := range a.Apks { + apk := &a.Apks[i] + if a.CVCode >= apk.VCode && apk.IsCompatible(device) { + return apk + } + } + for i := range a.Apks { + apk := &a.Apks[i] + if apk.IsCompatible(device) { + return apk + } + } + return nil +}