1// Copyright 2017 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package android
16
17import (
18	"encoding/json"
19	"fmt"
20	"strconv"
21)
22
23func init() {
24	RegisterSingletonType("api_levels", ApiLevelsSingleton)
25}
26
27func ApiLevelsSingleton() Singleton {
28	return &apiLevelsSingleton{}
29}
30
31type apiLevelsSingleton struct{}
32
33func createApiLevelsJson(ctx SingletonContext, file WritablePath,
34	apiLevelsMap map[string]int) {
35
36	jsonStr, err := json.Marshal(apiLevelsMap)
37	if err != nil {
38		ctx.Errorf(err.Error())
39	}
40
41	ctx.Build(pctx, BuildParams{
42		Rule:        WriteFile,
43		Description: "generate " + file.Base(),
44		Output:      file,
45		Args: map[string]string{
46			"content": string(jsonStr[:]),
47		},
48	})
49}
50
51func GetApiLevelsJson(ctx PathContext) WritablePath {
52	return PathForOutput(ctx, "api_levels.json")
53}
54
55var apiLevelsMapKey = NewOnceKey("ApiLevelsMap")
56
57func getApiLevelsMap(config Config) map[string]int {
58	return config.Once(apiLevelsMapKey, func() interface{} {
59		baseApiLevel := 9000
60		apiLevelsMap := map[string]int{
61			"G":     9,
62			"I":     14,
63			"J":     16,
64			"J-MR1": 17,
65			"J-MR2": 18,
66			"K":     19,
67			"L":     21,
68			"L-MR1": 22,
69			"M":     23,
70			"N":     24,
71			"N-MR1": 25,
72			"O":     26,
73			"O-MR1": 27,
74			"P":     28,
75			"Q":     29,
76		}
77		for i, codename := range config.PlatformVersionActiveCodenames() {
78			apiLevelsMap[codename] = baseApiLevel + i
79		}
80
81		return apiLevelsMap
82	}).(map[string]int)
83}
84
85// Converts an API level string into its numeric form.
86// * Codenames are decoded.
87// * Numeric API levels are simply converted.
88// * "current" is mapped to FutureApiLevel(10000)
89// * "minimum" is NDK specific and not handled with this. (refer normalizeNdkApiLevel in cc.go)
90func ApiStrToNum(ctx BaseModuleContext, apiLevel string) (int, error) {
91	if apiLevel == "current" {
92		return FutureApiLevel, nil
93	}
94	if num, ok := getApiLevelsMap(ctx.Config())[apiLevel]; ok {
95		return num, nil
96	}
97	if num, err := strconv.Atoi(apiLevel); err == nil {
98		return num, nil
99	}
100	return 0, fmt.Errorf("SDK version should be one of \"current\", <number> or <codename>: %q", apiLevel)
101}
102
103func (a *apiLevelsSingleton) GenerateBuildActions(ctx SingletonContext) {
104	apiLevelsMap := getApiLevelsMap(ctx.Config())
105	apiLevelsJson := GetApiLevelsJson(ctx)
106	createApiLevelsJson(ctx, apiLevelsJson, apiLevelsMap)
107}
108