mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
336 lines
12 KiB
Kotlin
Executable File
336 lines
12 KiB
Kotlin
Executable File
/*
|
|
* Copyright (C) 2019 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 com.android.aaptcompiler
|
|
|
|
import com.android.aaptcompiler.android.AConfiguration
|
|
import com.android.aaptcompiler.android.ResTableConfig
|
|
import com.android.aaptcompiler.android.isTruthy
|
|
|
|
/** attempt to parse the Mobile Country Code */
|
|
fun parseMcc(part: String, config: ConfigDescription): Boolean {
|
|
if (part == WILDCARD_NAME) {
|
|
config.mcc = 0
|
|
return true
|
|
}
|
|
|
|
// The only acceptable format is "mccDDD" (where D is a digit).
|
|
if (!part.startsWith("mcc") || part.length != 6) {
|
|
return false
|
|
}
|
|
val value = part.substring(3).toIntOrNull()?.toShort() ?: return false
|
|
config.mcc = value
|
|
return true
|
|
}
|
|
|
|
/** attempt to parse the Mobile Network Code */
|
|
fun parseMnc(part: String, config: ConfigDescription): Boolean {
|
|
if (part == WILDCARD_NAME) {
|
|
config.mnc = 0
|
|
return true
|
|
}
|
|
|
|
// The only acceptable format is "mncDDD" (where D is a digit).
|
|
if (!part.startsWith("mnc") || part.length != 6) {
|
|
return false
|
|
}
|
|
val value = part.substring(3).toIntOrNull()?.toShort() ?: return false
|
|
|
|
// Zero is reserved, so we need to use MINC_ZERO instead.
|
|
config.mnc = if (value.isTruthy()) value else AConfiguration.ACONFIGURATION_MNC_ZERO.toShort()
|
|
return true
|
|
}
|
|
|
|
// TODO(@daniellabar): Make more like the aapt2 parser.
|
|
fun parseLayoutDirection(part: String, config: ConfigDescription) : Boolean {
|
|
val value = when(part) {
|
|
WILDCARD_NAME -> ResTableConfig.SCREEN_LAYOUT.DIR_ANY
|
|
"ldltr" -> ResTableConfig.SCREEN_LAYOUT.DIR_LTR
|
|
"ldrtl" -> ResTableConfig.SCREEN_LAYOUT.DIR_RTL
|
|
else -> return false
|
|
}
|
|
// AND existing config with the mask and then OR with the found layout direction.
|
|
config.screenLayout =
|
|
maskAndApply(config.screenLayout, ResTableConfig.SCREEN_LAYOUT.DIR_MASK, value)
|
|
return true
|
|
}
|
|
|
|
fun parseSmallestScreenWidthDp(part: String, config: ConfigDescription): Boolean {
|
|
if (part == WILDCARD_NAME) {
|
|
config.smallestScreenWidthDp = 0
|
|
return true
|
|
}
|
|
if (!part.startsWith("sw") || !part.endsWith("dp")) {
|
|
return false
|
|
}
|
|
val value = part.substring(2, part.length-2).toIntOrNull() ?: return false
|
|
config.smallestScreenWidthDp = value
|
|
return true
|
|
}
|
|
|
|
fun parseScreenWidthDp(part: String, config: ConfigDescription): Boolean {
|
|
if (part == WILDCARD_NAME) {
|
|
config.screenWidthDp = 0
|
|
return true
|
|
}
|
|
if (!part.startsWith('w') || !part.endsWith("dp")) {
|
|
return false
|
|
}
|
|
val value = part.substring(1, part.length-2).toIntOrNull() ?: return false
|
|
config.screenWidthDp = value
|
|
return true
|
|
}
|
|
|
|
fun parseScreenHeightDp(part: String, config: ConfigDescription): Boolean {
|
|
if (part == WILDCARD_NAME) {
|
|
config.screenHeightDp = 0
|
|
return true
|
|
}
|
|
if (!part.startsWith('h') || !part.endsWith("dp")) {
|
|
return false
|
|
}
|
|
val value = part.substring(1, part.length-2).toIntOrNull() ?: return false
|
|
config.screenHeightDp = value
|
|
return true
|
|
}
|
|
|
|
fun parseScreenLayoutSize(part: String, config: ConfigDescription): Boolean {
|
|
val value = when (part) {
|
|
WILDCARD_NAME -> 0
|
|
"small" -> ResTableConfig.SCREEN_LAYOUT.SIZE_SMALL
|
|
"normal" -> ResTableConfig.SCREEN_LAYOUT.SIZE_NORMAL
|
|
"large" -> ResTableConfig.SCREEN_LAYOUT.SIZE_LARGE
|
|
"xlarge" -> ResTableConfig.SCREEN_LAYOUT.SIZE_XLARGE
|
|
else -> return false
|
|
}
|
|
// AND existing config with the mask and then OR with the found layout size.
|
|
config.screenLayout =
|
|
maskAndApply(config.screenLayout, ResTableConfig.SCREEN_LAYOUT.SIZE_MASK, value)
|
|
return true
|
|
}
|
|
|
|
fun parseScreenLayoutLong(part: String, config: ConfigDescription): Boolean {
|
|
val value = when (part) {
|
|
WILDCARD_NAME -> ResTableConfig.SCREEN_LAYOUT.SCREENLONG_ANY
|
|
"long" -> ResTableConfig.SCREEN_LAYOUT.SCREENLONG_YES
|
|
"notlong" -> ResTableConfig.SCREEN_LAYOUT.SCREENLONG_NO
|
|
else -> return false
|
|
}
|
|
// AND existing config with the mask and then OR with the found layout size.
|
|
config.screenLayout =
|
|
maskAndApply(config.screenLayout, ResTableConfig.SCREEN_LAYOUT.SCREENLONG_MASK, value)
|
|
return true
|
|
}
|
|
|
|
fun parseScreenRound(part: String, config: ConfigDescription): Boolean {
|
|
val value = when (part) {
|
|
WILDCARD_NAME -> ResTableConfig.SCREEN_LAYOUT2.SCREENROUND_ANY
|
|
"round" -> ResTableConfig.SCREEN_LAYOUT2.SCREENROUND_YES
|
|
"notround" -> ResTableConfig.SCREEN_LAYOUT2.SCREENROUND_NO
|
|
else -> return false
|
|
}
|
|
config.screenLayout2 =
|
|
maskAndApply(config.screenLayout2, ResTableConfig.SCREEN_LAYOUT2.SCREENROUND_MASK, value)
|
|
return true
|
|
}
|
|
|
|
fun parseWideColorGamut(part: String, config: ConfigDescription): Boolean {
|
|
val value = when (part) {
|
|
WILDCARD_NAME -> ResTableConfig.COLOR_MODE.WIDE_GAMUT_ANY
|
|
"widecg" -> ResTableConfig.COLOR_MODE.WIDE_GAMUT_YES
|
|
"nowidecg" -> ResTableConfig.COLOR_MODE.WIDE_GAMUT_NO
|
|
else -> return false
|
|
}
|
|
config.colorMode =
|
|
maskAndApply(config.colorMode, ResTableConfig.COLOR_MODE.WIDE_GAMUT_MASK, value)
|
|
return true
|
|
}
|
|
|
|
fun parseHdr(part: String, config: ConfigDescription): Boolean {
|
|
val value = when (part) {
|
|
WILDCARD_NAME -> ResTableConfig.COLOR_MODE.HDR_ANY
|
|
"highdr" -> ResTableConfig.COLOR_MODE.HDR_YES
|
|
"lowdr" -> ResTableConfig.COLOR_MODE.HDR_NO
|
|
else -> return false
|
|
}
|
|
config.colorMode = maskAndApply(config.colorMode, ResTableConfig.COLOR_MODE.HDR_MASK, value)
|
|
return true
|
|
}
|
|
|
|
fun parseOrientation(part: String, config: ConfigDescription): Boolean {
|
|
config.orientation = when (part) {
|
|
WILDCARD_NAME -> ResTableConfig.ORIENTATION.ANY
|
|
"port" -> ResTableConfig.ORIENTATION.PORT
|
|
"land" -> ResTableConfig.ORIENTATION.LAND
|
|
"square" -> ResTableConfig.ORIENTATION.SQUARE
|
|
else -> return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
fun parseUiModeType(part: String, config: ConfigDescription): Boolean {
|
|
val value = when (part) {
|
|
WILDCARD_NAME -> ResTableConfig.UI_MODE.TYPE_ANY
|
|
"desk" -> ResTableConfig.UI_MODE.TYPE_DESK
|
|
"car" -> ResTableConfig.UI_MODE.TYPE_CAR
|
|
"television" -> ResTableConfig.UI_MODE.TYPE_TELEVISION
|
|
"appliance" -> ResTableConfig.UI_MODE.TYPE_APPLIANCE
|
|
"watch" -> ResTableConfig.UI_MODE.TYPE_WATCH
|
|
"vrheadset" -> ResTableConfig.UI_MODE.TYPE_VR_HEADSET
|
|
else -> return false
|
|
}
|
|
config.uiMode = maskAndApply(config.uiMode, ResTableConfig.UI_MODE.TYPE_MASK, value)
|
|
return true
|
|
}
|
|
|
|
fun parseUiModeNight(part: String, config: ConfigDescription): Boolean {
|
|
val value = when (part) {
|
|
WILDCARD_NAME -> ResTableConfig.UI_MODE.NIGHT_ANY
|
|
"night" -> ResTableConfig.UI_MODE.NIGHT_YES
|
|
"notnight" -> ResTableConfig.UI_MODE.NIGHT_NO
|
|
else -> return false
|
|
}
|
|
config.uiMode = maskAndApply(config.uiMode, ResTableConfig.UI_MODE.NIGHT_MASK, value)
|
|
return true
|
|
}
|
|
|
|
fun parseDensity(part: String, config: ConfigDescription): Boolean {
|
|
if (part.isNotEmpty() && part[0].isLetter()) {
|
|
config.density = when (part) {
|
|
WILDCARD_NAME -> ResTableConfig.DENSITY.DEFAULT
|
|
"anydpi" -> ResTableConfig.DENSITY.ANY
|
|
"nodpi" -> ResTableConfig.DENSITY.NONE
|
|
"ldpi" -> ResTableConfig.DENSITY.LOW
|
|
"mdpi" -> ResTableConfig.DENSITY.MEDIUM
|
|
"tvdpi" -> ResTableConfig.DENSITY.TV
|
|
"hdpi" -> ResTableConfig.DENSITY.HIGH
|
|
"xhdpi" -> ResTableConfig.DENSITY.XHIGH
|
|
"xxhdpi" -> ResTableConfig.DENSITY.XXHIGH
|
|
"xxxhdpi" -> ResTableConfig.DENSITY.XXXHIGH
|
|
else -> return false
|
|
}
|
|
return true
|
|
} else {
|
|
// we might be dealing with "<number>dpi"
|
|
if (!part.endsWith("dpi")) {
|
|
return false
|
|
}
|
|
val value = part.substring(0, part.length-3).toIntOrNull() ?: return false
|
|
config.density = value
|
|
return true
|
|
}
|
|
}
|
|
|
|
fun parseTouchscreen(part: String, config: ConfigDescription): Boolean {
|
|
config.touchscreen = when (part) {
|
|
WILDCARD_NAME -> ResTableConfig.TOUCHSCREEN.ANY
|
|
"notouch" -> ResTableConfig.TOUCHSCREEN.NOTOUCH
|
|
"stylus" -> ResTableConfig.TOUCHSCREEN.STYLUS
|
|
"finger" -> ResTableConfig.TOUCHSCREEN.FINGER
|
|
else -> return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
fun parseKeysHidden(part: String, config: ConfigDescription): Boolean {
|
|
val value = when (part) {
|
|
WILDCARD_NAME -> ResTableConfig.INPUT_FLAGS.KEYSHIDDEN_ANY
|
|
"keysexposed" -> ResTableConfig.INPUT_FLAGS.KEYSHIDDEN_NO
|
|
"keyshidden" -> ResTableConfig.INPUT_FLAGS.KEYSHIDDEN_YES
|
|
"keyssoft" -> ResTableConfig.INPUT_FLAGS.KEYSHIDDEN_SOFT
|
|
else -> return false
|
|
}
|
|
config.inputFlags =
|
|
maskAndApply(config.inputFlags, ResTableConfig.INPUT_FLAGS.KEYSHIDDEN_MASK, value)
|
|
return true
|
|
}
|
|
|
|
fun parseKeyboard(part: String, config: ConfigDescription): Boolean {
|
|
config.keyboard = when (part) {
|
|
WILDCARD_NAME -> ResTableConfig.KEYBOARD.ANY
|
|
"nokeys" -> ResTableConfig.KEYBOARD.NOKEYS
|
|
"qwerty" -> ResTableConfig.KEYBOARD.QWERTY
|
|
"12key" -> ResTableConfig.KEYBOARD.TWELVEKEY
|
|
else -> return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
fun parseNavHidden(part: String, config: ConfigDescription): Boolean {
|
|
val value = when (part) {
|
|
WILDCARD_NAME -> ResTableConfig.INPUT_FLAGS.NAVHIDDEN_ANY
|
|
"navexposed" -> ResTableConfig.INPUT_FLAGS.NAVHIDDEN_NO
|
|
"navhidden" -> ResTableConfig.INPUT_FLAGS.NAVHIDDEN_YES
|
|
else -> return false
|
|
}
|
|
config.inputFlags =
|
|
maskAndApply(config.inputFlags, ResTableConfig.INPUT_FLAGS.NAVHIDDEN_MASK, value)
|
|
return true
|
|
}
|
|
|
|
fun parseNavigation(part: String, config: ConfigDescription): Boolean {
|
|
config.navigation = when (part) {
|
|
WILDCARD_NAME -> ResTableConfig.NAVIGATION.ANY
|
|
"nonav" -> ResTableConfig.NAVIGATION.NONAV
|
|
"dpad" -> ResTableConfig.NAVIGATION.DPAD
|
|
"trackball" -> ResTableConfig.NAVIGATION.TRACKBALL
|
|
"wheel" -> ResTableConfig.NAVIGATION.WHEEL
|
|
else -> return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
fun parseScreenSize(part: String, config: ConfigDescription): Boolean {
|
|
if (part == WILDCARD_NAME) {
|
|
config.screenWidth = 0
|
|
config.screenHeight = 0
|
|
return true
|
|
}
|
|
|
|
// Format is NxM
|
|
val width = part.substringBefore('x').toIntOrNull() ?: return false
|
|
val height = part.substringAfter('x').toIntOrNull() ?: return false
|
|
if (width < height) {
|
|
return false
|
|
}
|
|
config.screenWidth = width
|
|
config.screenHeight = height
|
|
return true
|
|
}
|
|
|
|
fun parseVersion(part: String, config: ConfigDescription): Boolean {
|
|
if (part == WILDCARD_NAME) {
|
|
config.sdkVersion = 0
|
|
config.minorVersion = 0
|
|
return true
|
|
}
|
|
|
|
// Format is vN
|
|
if (!part.startsWith('v')) {
|
|
return false
|
|
}
|
|
val version = part.substring(1).toIntOrNull()?.toShort() ?: return false
|
|
config.sdkVersion = version
|
|
config.minorVersion = 0
|
|
return true
|
|
}
|
|
|
|
fun maskAndApply(current: Byte, mask: Int, value: Byte) =
|
|
maskAndApply(current.toInt(), mask, value.toInt()).toByte()
|
|
fun maskAndApply(current: Int, mask: Int, value: Int): Int =
|
|
(current and mask.inv()) or value
|
|
|