build: reorganize and reconfigure modules to resolve dependency resolution errors

Gradle, for some reason, does not the path of modules to identify them uniquely. Instead, the 'build id' is used to do so, which consists of the maven group and artifact ID. So, even if two modules are located in separate directories, but have the name group and artifact ID, including both of them in other modules may result in dependency resolution errors.
This commit is contained in:
Akash Yadav
2024-05-29 13:11:44 +05:30
parent c0c185cfb7
commit 1efd6a04d5
2457 changed files with 1069 additions and 709 deletions
+1
View File
@@ -0,0 +1 @@
/build
+50
View File
@@ -0,0 +1,50 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
import com.itsaky.androidide.build.config.BuildConfig
plugins {
id("com.android.library")
id("kotlin-android")
id("kotlin-kapt")
}
groupConfig {
groupIdSuffix.set("xml")
}
android {
namespace = "${BuildConfig.packageName}.xml"
}
dependencies {
kapt(libs.google.auto.service)
api(projects.utilities.lookup)
api(projects.xml.aaptcompiler)
implementation(libs.common.kotlin)
implementation(libs.composite.jdt)
implementation(libs.google.auto.service.annotations)
implementation(projects.core.common)
implementation(projects.logging.logger)
testImplementation(libs.tests.junit)
testImplementation(libs.tests.robolectric)
testImplementation(libs.tests.google.truth)
}
@@ -0,0 +1,324 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.internal.resources
import com.android.SdkConstants
import com.android.SdkConstants.FN_INTENT_ACTIONS_ACTIVITY
import com.android.SdkConstants.FN_INTENT_ACTIONS_BROADCAST
import com.android.SdkConstants.FN_INTENT_ACTIONS_SERVICE
import com.android.SdkConstants.FN_INTENT_CATEGORIES
import com.android.SdkConstants.OS_PLATFORM_ATTRS_MANIFEST_XML
import com.android.aaptcompiler.AaptResourceType
import com.android.aaptcompiler.BlameLogger
import com.android.aaptcompiler.ConfigDescription
import com.android.aaptcompiler.ResourceName
import com.android.aaptcompiler.ResourceTable
import com.android.aaptcompiler.Source
import com.android.aaptcompiler.TableExtractor
import com.android.aaptcompiler.TableExtractorOptions
import com.android.aaptcompiler.extractPathData
import com.google.auto.service.AutoService
import com.itsaky.androidide.aapt.logging.IDELogger
import com.itsaky.androidide.layoutlib.resources.ResourceVisibility.PUBLIC
import com.itsaky.androidide.xml.internal.resources.DefaultResourceTableRegistry.SingleLineValueEntryType.ACTIVITY_ACTIONS
import com.itsaky.androidide.xml.internal.resources.DefaultResourceTableRegistry.SingleLineValueEntryType.BROADCAST_ACTIONS
import com.itsaky.androidide.xml.internal.resources.DefaultResourceTableRegistry.SingleLineValueEntryType.CATEGORIES
import com.itsaky.androidide.xml.internal.resources.DefaultResourceTableRegistry.SingleLineValueEntryType.FEATURES
import com.itsaky.androidide.xml.internal.resources.DefaultResourceTableRegistry.SingleLineValueEntryType.SERVICE_ACTIONS
import com.itsaky.androidide.xml.resources.ResourceTableRegistry
import com.itsaky.androidide.xml.resources.ResourceTableRegistry.Companion.PCK_ANDROID
import org.slf4j.LoggerFactory
import java.io.File
import java.util.concurrent.ConcurrentHashMap
/**
* Default implementation of the [ResourceTableRegistry].
*
* @author Akash Yadav
*/
@AutoService(ResourceTableRegistry::class)
class DefaultResourceTableRegistry : ResourceTableRegistry {
/**
* Represents the type of single line entries read from files.
*
* @property filename The filename which contains the single-line entries.
*/
internal enum class SingleLineValueEntryType(val filename: String) {
ACTIVITY_ACTIONS(FN_INTENT_ACTIONS_ACTIVITY),
BROADCAST_ACTIONS(FN_INTENT_ACTIONS_BROADCAST),
SERVICE_ACTIONS(FN_INTENT_ACTIONS_SERVICE),
CATEGORIES(FN_INTENT_CATEGORIES),
FEATURES("features.txt")
}
private val tables = ConcurrentHashMap<String, ResourceTable>()
private val platformTables = ConcurrentHashMap<String, ResourceTable>()
private val manifestAttrs = ConcurrentHashMap<String, ResourceTable>()
private val singleLineValueEntries =
ConcurrentHashMap<String, ConcurrentHashMap<SingleLineValueEntryType, List<String>>>()
companion object {
private val log = LoggerFactory.getLogger(DefaultResourceTableRegistry::class.java)
}
override var isLoggingEnabled: Boolean = true
override fun forPackage(name: String, vararg resDirs: File): ResourceTable? {
if (name == PCK_ANDROID) {
return platformResourceTable(resDirs.iterator().next())
}
return tables[name]
?: createTable(*resDirs)?.also {
tables[name] = it
it.packages.firstOrNull()?.name = name
resDirs.forEach { resDir ->
addFileReferences(it, name, resDir)
}
}
}
override fun forPlatformDir(platform: File): ResourceTable? {
getManifestAttrTable(platform)
getActivityActions(platform)
getBroadcastActions(platform)
getServiceActions(platform)
getCategories(platform)
getFeatures(platform)
return super.forPlatformDir(platform)
}
override fun getManifestAttrTable(platform: File): ResourceTable? {
return manifestAttrs[platform.path]
?: createManifestAttrTable(platform)?.also {
manifestAttrs[platform.path] = it
it.packages.firstOrNull()?.name = PCK_ANDROID
}
}
override fun getActivityActions(platform: File): List<String> {
return getSingleLineEntry(platform, ACTIVITY_ACTIONS)
}
override fun getBroadcastActions(platform: File): List<String> {
return getSingleLineEntry(platform, BROADCAST_ACTIONS)
}
override fun getServiceActions(platform: File): List<String> {
return getSingleLineEntry(platform, SERVICE_ACTIONS)
}
override fun getCategories(platform: File): List<String> {
return getSingleLineEntry(platform, CATEGORIES)
}
override fun getFeatures(platform: File): List<String> {
return getSingleLineEntry(platform, FEATURES)
}
override fun removeTable(packageName: String) {
tables.remove(packageName)
}
override fun clear() {
tables.clear()
}
private fun getSingleLineEntry(platform: File, type: SingleLineValueEntryType): List<String> {
var entries = singleLineValueEntries[platform.path]
if (entries == null) {
entries = readSingleLineEntry(platform, type)
singleLineValueEntries[platform.path] = entries
}
return entries[type]
?: run {
readSingleLineEntriesTo(platform, type, entries)
entries[type] ?: emptyList()
}
}
private fun readSingleLineEntry(
platform: File,
type: SingleLineValueEntryType
): ConcurrentHashMap<SingleLineValueEntryType, List<String>> {
val map = ConcurrentHashMap<SingleLineValueEntryType, List<String>>()
readSingleLineEntriesTo(platform, type, map)
return map
}
private fun readSingleLineEntriesTo(
platform: File,
type: SingleLineValueEntryType,
map: ConcurrentHashMap<SingleLineValueEntryType, List<String>>
) {
val file = File(platform, "${SdkConstants.FD_DATA}/${type.filename}")
if (!file.exists() || !file.canRead()) {
return
}
map[type] = file.readLines()
}
private fun createManifestAttrTable(platform: File): ResourceTable? {
val attrs = File(platform, OS_PLATFORM_ATTRS_MANIFEST_XML)
if (!attrs.exists()) {
return null
}
val logger = BlameLogger(IDELogger)
val table = ResourceTable(logger = logger)
val options = getDefaultOptions()
extractTable(attrs, table, options, logger)
return table
}
private fun platformResourceTable(dir: File): ResourceTable? {
return platformTables[dir.path]
?: createTable(dir)?.also { table ->
platformTables[dir.path] = table
table.packages.firstOrNull()?.name = PCK_ANDROID
addFileReferences(table, PCK_ANDROID, dir)
}
}
private fun createTable(vararg resDirs: File): ResourceTable? {
if (resDirs.isEmpty()) {
return null
}
if (isLoggingEnabled) {
log.info("Creating resource table for {} resource directories", resDirs.size)
}
val logger = BlameLogger(IDELogger)
val table = ResourceTable()
val options = getDefaultOptions()
for (resDir in resDirs) {
val values = File(resDir, "values")
if (!values.exists() || !values.isDirectory) {
continue
}
updateFromDirectory(values, table, options, logger)
}
return table
}
private fun addFileReferences(table: ResourceTable, pck: String, resDir: File) {
resDir.listFiles()?.forEach { dir ->
if (dir.name.startsWith(SdkConstants.FD_RES_VALUES)) {
return@forEach
}
dir.listFiles()?.forEach { file ->
var typeName = dir.name
if (typeName.contains('-')) {
typeName = typeName.substringBefore('-')
}
val type = try {
AaptResourceType.valueOf(typeName.uppercase())
} catch (error: Exception) {
if (isLoggingEnabled) {
log.warn("Unknown resource type: {} :: {}", typeName.uppercase(), error.message)
}
AaptResourceType.UNKNOWN
}
val resName = ResourceName(pck, type, file.nameWithoutExtension)
table.addFileReference(resName, ConfigDescription(), Source(file.path), file.path)
}
}
}
private fun getDefaultOptions(): TableExtractorOptions {
return TableExtractorOptions(translatable = true, errorOnPositionalArgs = false,
visibility = PUBLIC)
}
private fun updateFromDirectory(
directory: File,
table: ResourceTable,
options: TableExtractorOptions,
logger: BlameLogger = BlameLogger(IDELogger)
) {
directory.listFiles()?.forEach {
if (it.isDirectory || it.extension != "xml") {
return@forEach
}
updateFromFile(it, table, options, logger)
}
}
private fun updateFromFile(
it: File,
table: ResourceTable,
options: TableExtractorOptions,
logger: BlameLogger
) {
if (it.path.endsWith(OS_PLATFORM_ATTRS_MANIFEST_XML)) {
// This is stored in another resource table
return
}
extractTable(it, table, options, logger)
return
}
private fun extractTable(
file: File,
table: ResourceTable,
options: TableExtractorOptions,
logger: BlameLogger
) {
val pathData = extractPathData(file)
if (pathData.extension != "xml") {
// Cannot parse any other file types
return
}
val extractor =
TableExtractor(
table = table,
source = pathData.source,
config = pathData.config,
options = options,
logger = logger
)
pathData.file.inputStream().use { stream ->
try {
extractor.extract(stream)
} catch (err: Exception) {
if (isLoggingEnabled) {
log.warn("Failed to compile {}", pathData.file)
}
}
}
}
}
@@ -0,0 +1,36 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.internal.versions
import com.itsaky.androidide.xml.versions.ApiVersions
import com.itsaky.androidide.xml.versions.ClassInfo
import java.util.concurrent.ConcurrentHashMap
/** @author Akash Yadav */
internal class DefaultApiVersions : ApiVersions {
val classes = ConcurrentHashMap<String, ClassInfo>()
override fun getClass(name: String): ClassInfo? {
return classes[name.replace('.', '/')]
}
internal fun putClass(name: String, info: ClassInfo) {
classes[name] = info
}
}
@@ -0,0 +1,255 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.internal.versions
import com.google.auto.service.AutoService
import com.itsaky.androidide.xml.versions.ApiVersions
import com.itsaky.androidide.xml.versions.ApiVersionsRegistry
import com.itsaky.androidide.xml.versions.ClassInfo
import com.itsaky.androidide.xml.versions.FieldInfo
import com.itsaky.androidide.xml.versions.Info
import com.itsaky.androidide.xml.versions.MethodInfo
import org.slf4j.LoggerFactory
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserFactory
import java.io.File
import java.util.concurrent.ConcurrentHashMap
/**
* Default implementation of [ApiVersionsRegistry].
*
* @author Akash Yadav
*/
@AutoService(ApiVersionsRegistry::class)
class DefaultApiVersionsRegistry : ApiVersionsRegistry {
private val versions = ConcurrentHashMap<String, ApiVersions>()
companion object {
private val log = LoggerFactory.getLogger(DefaultApiVersionsRegistry::class.java)
}
override var isLoggingEnabled: Boolean = true
override fun forPlatformDir(platform: File): ApiVersions? {
var version = versions[platform.path]
if (version != null) {
return version
}
version = readApiVersions(platform) ?: return null
versions[platform.path] = version
return version
}
private fun readApiVersions(platform: File): ApiVersions? {
val versionsFile = File(platform, "data/api-versions.xml")
if (!versionsFile.exists() || !versionsFile.isFile) {
return null
}
if (isLoggingEnabled) {
log.info("Creating API versions table for platform dir: $platform")
}
return versionsFile.bufferedReader().use {
val parser =
XmlPullParserFactory.newInstance().run {
isNamespaceAware = false
return@run newPullParser().run {
setInput(it)
this
}
}
readApiVersions(parser)
}
}
private fun readApiVersions(parser: XmlPullParser): ApiVersions {
val versions = DefaultApiVersions()
var event = parser.eventType
var apiEncountered = false
while (event != XmlPullParser.END_DOCUMENT) {
if (event == XmlPullParser.START_TAG) {
val tag = parser.name
if (tag == "api") {
apiEncountered = true
event = parser.next()
continue
}
if (!apiEncountered) {
throw IllegalStateException("<api> tag not found")
}
val info = readTag(parser)
if (info != null && info is ClassInfo) {
versions.putClass(info.name, info)
}
}
event = parser.next()
}
return versions
}
private fun readTag(parser: XmlPullParser): Info? {
return when (parser.name) {
"class" -> readClassInfo(parser)
"method" -> readMethodInfo(parser)
"field" -> readFieldInfo(parser)
else -> null
}
}
private fun readMethodInfo(parser: XmlPullParser): Info {
val name = parser.readName()
return DefaultMethodInfo(
name = name,
since = parser.readSince(),
removed = parser.readRemoved(),
deprecated = parser.readDeprecated(),
simpleName = name.substringBefore('(')
)
}
private fun readFieldInfo(parser: XmlPullParser): Info {
return DefaultFieldInfo(
name = parser.readName(),
since = parser.readSince(),
removed = parser.readRemoved(),
deprecated = parser.readDeprecated()
)
}
private fun readClassInfo(parser: XmlPullParser): ClassInfo {
return DefaultClassInfo(
name = parser.readName(),
since = parser.readSince(),
removed = parser.readRemoved(),
deprecated = parser.readDeprecated()
)
.apply {
val depth = parser.depth
var event = parser.next()
while (event != XmlPullParser.END_DOCUMENT) {
if (event == XmlPullParser.END_TAG && parser.depth == depth) {
break
}
if (event != XmlPullParser.START_TAG) {
event = parser.next()
continue
}
val info = readTag(parser)
if (info == null) {
event = parser.next()
continue
}
when (info) {
is FieldInfo -> this.fields[info.name] = info
is MethodInfo -> {
var methods = this.methods[info.simpleName]
if (methods == null) {
methods = mutableListOf()
}
methods.add(info)
this.methods[info.simpleName] = methods
}
}
event = parser.next()
}
}
}
private fun XmlPullParser.readName(): String {
return readString("name")
}
private fun XmlPullParser.readSince(): Int {
return readInt("since")
}
private fun XmlPullParser.readRemoved(): Int {
return readInt("removed")
}
private fun XmlPullParser.readDeprecated(): Int {
return readInt("deprecated")
}
private fun XmlPullParser.readInt(name: String, default: Int = -1): Int {
return read(this, name) {
if (it.isNullOrBlank()) {
return@read default
}
return@read it.toInt()
}
}
private fun XmlPullParser.readString(name: String, default: String = ""): String {
return read(this, name) {
if (it.isNullOrBlank()) {
return@read default
}
return@read it
}
}
private fun <T> read(parser: XmlPullParser, name: String, convert: (String?) -> T): T {
val index = parser.attrIndex(name)
if (index != -1) {
return convert(parser.value(index))
}
return convert("")
}
override fun clear() {
versions.clear()
}
/**
* Find the index of the attribute with the given name.
*
* @param name The name of the attribute to look for.
* @return The index of the attribute or `-1`.
*/
private fun XmlPullParser.attrIndex(name: String): Int {
for (i in 0 until this.attributeCount) {
if (this.getAttributeName(i) == name) {
return i
}
}
return -1
}
/**
* Get the value of the attribute at the given index.
*
* @param index The index of the attribute.
* @return The value of the attribute.
*/
private fun XmlPullParser.value(index: Int): String? {
return getAttributeValue(index)
}
}
@@ -0,0 +1,53 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.internal.versions
import com.itsaky.androidide.xml.versions.ClassInfo
import com.itsaky.androidide.xml.versions.FieldInfo
import com.itsaky.androidide.xml.versions.MethodInfo
import org.eclipse.jdt.core.Signature
import java.util.concurrent.ConcurrentHashMap
/**
* Default implementation of [ClassInfo]
*
* @author Akash Yadav
*/
internal class DefaultClassInfo(name: String, since: Int, removed: Int, deprecated: Int) :
DefaultInfo(name, since, removed, deprecated), ClassInfo {
internal val fields = ConcurrentHashMap<String, FieldInfo>()
internal val methods = ConcurrentHashMap<String, MutableList<MethodInfo>>()
override fun getField(name: String): FieldInfo? {
return fields[name]
}
override fun getMethod(name: String, vararg params: String): MethodInfo? {
val methods = methods[name] ?: return null
val paramTypes = Array(size = params.size) { "" }
params.forEachIndexed { index, type ->
paramTypes[index] = Signature.createTypeSignature(type.replace('.', '/'), true)
}
return methods.find {
val methodParams = Signature.getParameterTypes(it.name)
methodParams != null && paramTypes.contentDeepEquals(methodParams)
}
}
}
@@ -0,0 +1,24 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.internal.versions
import com.itsaky.androidide.xml.versions.FieldInfo
/** @author Akash Yadav */
class DefaultFieldInfo(name: String, since: Int, removed: Int, deprecated: Int) :
DefaultInfo(name, since, removed, deprecated), FieldInfo
@@ -0,0 +1,53 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.internal.versions
import com.itsaky.androidide.xml.versions.Info
/** @author Akash Yadav */
open class DefaultInfo(
override val name: String,
override val since: Int,
override val removed: Int,
override val deprecated: Int
) : Info {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is DefaultInfo) return false
if (name != other.name) return false
if (since != other.since) return false
if (removed != other.removed) return false
if (deprecated != other.deprecated) return false
return true
}
override fun hashCode(): Int {
var result = name.hashCode()
result = 31 * result + since
result = 31 * result + removed
result = 31 * result + deprecated
return result
}
override fun toString(): String {
return "DefaultInfo(name='$name', since=$since, removed=$removed, deprecated=$deprecated)"
}
}
@@ -0,0 +1,50 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.internal.versions
import com.itsaky.androidide.xml.versions.MethodInfo
/** @author Akash Yadav */
internal class DefaultMethodInfo(
override val simpleName: String,
name: String,
since: Int,
removed: Int,
deprecated: Int
) : DefaultInfo(name, since, removed, deprecated), MethodInfo {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is DefaultMethodInfo) return false
if (!super.equals(other)) return false
if (simpleName != other.simpleName) return false
return true
}
override fun hashCode(): Int {
var result = super.hashCode()
result = 31 * result + simpleName.hashCode()
return result
}
override fun toString(): String {
return "DefaultMethodInfo(simpleName='$simpleName')"
}
}
@@ -0,0 +1,181 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.internal.widgets
import com.itsaky.androidide.xml.internal.widgets.util.DefaultWidget
import com.itsaky.androidide.xml.internal.widgets.util.WidgetParser
import com.itsaky.androidide.xml.widgets.Widget
import com.itsaky.androidide.xml.widgets.WidgetTable
import org.slf4j.LoggerFactory
/**
* Default implementation of [WidgetTable].
*
* @author Akash Yadav
*/
class DefaultWidgetTable : WidgetTable {
private val root: WidgetNode = WidgetNode(name = "", isWidget = false)
companion object {
private val log = LoggerFactory.getLogger(DefaultWidgetTable::class.java)
}
override fun getWidget(name: String): Widget? {
val node = getNode(name)!!
if (!node.isWidget) {
return null
}
return node.widget
}
override fun findWidgetWithSimpleName(name: String): Widget? {
return findWidgetWithSimpleName(name, root)
}
override fun getAllWidgets(): Set<Widget> {
val result = mutableSetOf<Widget>()
root.children.values.forEach { result.addAll(collectWidgets(it)) }
return result
}
private fun collectWidgets(node: WidgetNode): Set<Widget> {
val result = mutableSetOf<Widget>()
if (node.widget != null) {
result.add(node.widget)
}
node.children.values.forEach { result.addAll(collectWidgets(it)) }
return result
}
private fun findWidgetWithSimpleName(name: String, root: WidgetNode): Widget? {
for (child in root.children.values) {
if (child.widget?.simpleName == name) {
return child.widget
}
if (child.children.isEmpty()) {
continue
}
val inner = findWidgetWithSimpleName(name, child)
if (inner != null) {
return inner
}
}
return null
}
internal fun putWidget(line: String) {
val widget =
WidgetParser.parse(line)
?: run {
log.debug("Cannot parse widget from line: {}", line)
return
}
putWidget(widget)
}
internal fun putWidget(widget: DefaultWidget) {
val name = widget.qualifiedName.substringBeforeLast('.')
val node = getNode(name)!!
val existing = node.children[widget.simpleName]
val newNode = WidgetNode(name = widget.qualifiedName, isWidget = true, widget = widget)
if (existing == null) {
node.children[widget.simpleName] = newNode
return
}
// Happens when the inner classes are defined earlier than the parent class
// For example, when FrameLayout.LayoutParams is defined earlier than FrameLayout
newNode.children.putAll(existing.children)
node.children[widget.simpleName] = newNode
}
@JvmOverloads
fun getNode(name: String, createIfNotPresent: Boolean = true): WidgetNode? {
if (name.isBlank()) {
return root
}
if (!name.contains('.')) {
return if (createIfNotPresent) {
root.children.computeIfAbsent(name) { WidgetNode(name = name, isWidget = false) }
} else {
root.children[name]
}
}
val segments = name.split('.')
var node: WidgetNode? = root
for (segment in segments) {
if (node == null) {
break
}
node =
if (createIfNotPresent) {
node.children.computeIfAbsent(segment) { WidgetNode(name = segment, isWidget = false) }
} else {
node.children[segment]
}
}
return node
}
inner class WidgetNode(
val name: String,
val isWidget: Boolean,
val widget: DefaultWidget? = null,
val children: MutableMap<String, WidgetNode> = mutableMapOf()
) {
override fun toString(): String {
return "WidgetNode(name='$name', isWidget=$isWidget, widget=$widget, children=$children)"
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is WidgetNode) return false
if (name != other.name) return false
if (isWidget != other.isWidget) return false
if (widget != other.widget) return false
if (children != other.children) return false
return true
}
override fun hashCode(): Int {
var result = name.hashCode()
result = 31 * result + isWidget.hashCode()
result = 31 * result + (widget?.hashCode() ?: 0)
result = 31 * result + children.hashCode()
return result
}
}
}
@@ -0,0 +1,80 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.internal.widgets
import com.google.auto.service.AutoService
import com.itsaky.androidide.xml.widgets.WidgetTable
import com.itsaky.androidide.xml.widgets.WidgetTableRegistry
import org.slf4j.LoggerFactory
import java.io.File
import java.util.concurrent.ConcurrentHashMap
/**
* Default implementation of the [WidgetTableRegistry].
*
* @author Akash Yadav
*/
@AutoService(WidgetTableRegistry::class)
class DefaultWidgetTableRegistry : WidgetTableRegistry {
private val tables = ConcurrentHashMap<String, WidgetTable>()
companion object {
private val log = LoggerFactory.getLogger(DefaultWidgetTableRegistry::class.java)
}
override var isLoggingEnabled: Boolean = true
override fun forPlatformDir(platform: File): WidgetTable? {
var table = tables[platform.path]
if (table != null) {
return table
}
table = createTable(platform) ?: return null
tables[platform.path] = table
return table
}
private fun createTable(platformDir: File): WidgetTable? {
val widgets = File(platformDir, "data/widgets.txt")
if (!widgets.exists() || !widgets.isFile) {
if (isLoggingEnabled) {
log.warn("'widgets.txt' file does not exist in {}/data directory", platformDir.absolutePath)
}
return null
}
if (isLoggingEnabled) {
log.info("Creating widget table for platform dir: {}", platformDir)
}
return widgets.inputStream().bufferedReader().useLines {
val table = DefaultWidgetTable()
it.forEach { line ->
table.putWidget(line)
}
table
}
}
override fun clear() {
tables.clear()
}
}
@@ -0,0 +1,32 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.internal.widgets.util
import com.itsaky.androidide.xml.widgets.Widget
import com.itsaky.androidide.xml.widgets.WidgetType
/**
* Default implementation of [Widget].
* @author Akash Yadav
*/
class DefaultWidget(
override val simpleName: String,
override val qualifiedName: String,
override val type: WidgetType,
override val superclasses: List<String>
) : Widget
@@ -0,0 +1,44 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.internal.widgets.util
import com.itsaky.androidide.xml.widgets.WidgetType
/**
* Parses widget information from the string representation.
*
* @author Akash Yadav
*/
object WidgetParser {
/**
* Parses a [DefaultWidget] from the given string representation. Returns `null` if cannot parse.
*/
fun parse(line: String): DefaultWidget? {
val split = line.split(' ')
if (split.size < 2) {
return null
}
val type = WidgetType.Factory.forChar(split[0][0]) ?: return null
val name = split[0].substring(1)
val simpleName = name.substringAfterLast('.')
val superclasses = split.subList(1, split.size)
return DefaultWidget(simpleName, name, type, superclasses)
}
}
@@ -0,0 +1,318 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.permissions;
/**
* Manifest permissions extracted from `android/Manifest$permission.class` android
* `android/Manifest$permission_group.class` entries in the `android.jar` of API 33.
*
* <p><b>Auto-generated using ClassFileReader</b>
*
* <p>TODO Check if we could eliminate this and extract these at runtime when the project is
* initialized.
*
* @author Akash Yadav
*/
public class ManifestPermissionConstants {
public static final String ACCEPT_HANDOVER = "android.permission.ACCEPT_HANDOVER";
public static final String ACCESS_BACKGROUND_LOCATION =
"android.permission.ACCESS_BACKGROUND_LOCATION";
public static final String ACCESS_BLOBS_ACROSS_USERS =
"android.permission.ACCESS_BLOBS_ACROSS_USERS";
public static final String ACCESS_CHECKIN_PROPERTIES =
"android.permission.ACCESS_CHECKIN_PROPERTIES";
public static final String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
public static final String ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION";
public static final String ACCESS_LOCATION_EXTRA_COMMANDS =
"android.permission.ACCESS_LOCATION_EXTRA_COMMANDS";
public static final String ACCESS_MEDIA_LOCATION = "android.permission.ACCESS_MEDIA_LOCATION";
public static final String ACCESS_NETWORK_STATE = "android.permission.ACCESS_NETWORK_STATE";
public static final String ACCESS_NOTIFICATION_POLICY =
"android.permission.ACCESS_NOTIFICATION_POLICY";
public static final String ACCESS_WIFI_STATE = "android.permission.ACCESS_WIFI_STATE";
public static final String ACCOUNT_MANAGER = "android.permission.ACCOUNT_MANAGER";
public static final String ACTIVITY_RECOGNITION = "android.permission.ACTIVITY_RECOGNITION";
public static final String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL";
public static final String ANSWER_PHONE_CALLS = "android.permission.ANSWER_PHONE_CALLS";
public static final String BATTERY_STATS = "android.permission.BATTERY_STATS";
public static final String BIND_ACCESSIBILITY_SERVICE =
"android.permission.BIND_ACCESSIBILITY_SERVICE";
public static final String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
public static final String BIND_AUTOFILL_SERVICE = "android.permission.BIND_AUTOFILL_SERVICE";
public static final String BIND_CALL_REDIRECTION_SERVICE =
"android.permission.BIND_CALL_REDIRECTION_SERVICE";
public static final String BIND_CARRIER_MESSAGING_CLIENT_SERVICE =
"android.permission.BIND_CARRIER_MESSAGING_CLIENT_SERVICE";
public static final String BIND_CARRIER_MESSAGING_SERVICE =
"android.permission.BIND_CARRIER_MESSAGING_SERVICE";
public static final String BIND_CARRIER_SERVICES = "android.permission.BIND_CARRIER_SERVICES";
public static final String BIND_CHOOSER_TARGET_SERVICE =
"android.permission.BIND_CHOOSER_TARGET_SERVICE";
public static final String BIND_COMPANION_DEVICE_SERVICE =
"android.permission.BIND_COMPANION_DEVICE_SERVICE";
public static final String BIND_CONDITION_PROVIDER_SERVICE =
"android.permission.BIND_CONDITION_PROVIDER_SERVICE";
public static final String BIND_CONTROLS = "android.permission.BIND_CONTROLS";
public static final String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
public static final String BIND_DREAM_SERVICE = "android.permission.BIND_DREAM_SERVICE";
public static final String BIND_INCALL_SERVICE = "android.permission.BIND_INCALL_SERVICE";
public static final String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
public static final String BIND_MIDI_DEVICE_SERVICE =
"android.permission.BIND_MIDI_DEVICE_SERVICE";
public static final String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
public static final String BIND_NOTIFICATION_LISTENER_SERVICE =
"android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
public static final String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
public static final String BIND_QUICK_ACCESS_WALLET_SERVICE =
"android.permission.BIND_QUICK_ACCESS_WALLET_SERVICE";
public static final String BIND_QUICK_SETTINGS_TILE =
"android.permission.BIND_QUICK_SETTINGS_TILE";
public static final String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
public static final String BIND_SCREENING_SERVICE = "android.permission.BIND_SCREENING_SERVICE";
public static final String BIND_TELECOM_CONNECTION_SERVICE =
"android.permission.BIND_TELECOM_CONNECTION_SERVICE";
public static final String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
public static final String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
public static final String BIND_TV_INTERACTIVE_APP = "android.permission.BIND_TV_INTERACTIVE_APP";
public static final String BIND_VISUAL_VOICEMAIL_SERVICE =
"android.permission.BIND_VISUAL_VOICEMAIL_SERVICE";
public static final String BIND_VOICE_INTERACTION = "android.permission.BIND_VOICE_INTERACTION";
public static final String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
public static final String BIND_VR_LISTENER_SERVICE =
"android.permission.BIND_VR_LISTENER_SERVICE";
public static final String BIND_WALLPAPER = "android.permission.BIND_WALLPAPER";
public static final String BLUETOOTH = "android.permission.BLUETOOTH";
public static final String BLUETOOTH_ADMIN = "android.permission.BLUETOOTH_ADMIN";
public static final String BLUETOOTH_ADVERTISE = "android.permission.BLUETOOTH_ADVERTISE";
public static final String BLUETOOTH_CONNECT = "android.permission.BLUETOOTH_CONNECT";
public static final String BLUETOOTH_PRIVILEGED = "android.permission.BLUETOOTH_PRIVILEGED";
public static final String BLUETOOTH_SCAN = "android.permission.BLUETOOTH_SCAN";
public static final String BODY_SENSORS = "android.permission.BODY_SENSORS";
public static final String BODY_SENSORS_BACKGROUND = "android.permission.BODY_SENSORS_BACKGROUND";
public static final String BROADCAST_PACKAGE_REMOVED =
"android.permission.BROADCAST_PACKAGE_REMOVED";
public static final String BROADCAST_SMS = "android.permission.BROADCAST_SMS";
public static final String BROADCAST_STICKY = "android.permission.BROADCAST_STICKY";
public static final String BROADCAST_WAP_PUSH = "android.permission.BROADCAST_WAP_PUSH";
public static final String CALL_COMPANION_APP = "android.permission.CALL_COMPANION_APP";
public static final String CALL_PHONE = "android.permission.CALL_PHONE";
public static final String CALL_PRIVILEGED = "android.permission.CALL_PRIVILEGED";
public static final String CAMERA = "android.permission.CAMERA";
public static final String CAPTURE_AUDIO_OUTPUT = "android.permission.CAPTURE_AUDIO_OUTPUT";
public static final String CHANGE_COMPONENT_ENABLED_STATE =
"android.permission.CHANGE_COMPONENT_ENABLED_STATE";
public static final String CHANGE_CONFIGURATION = "android.permission.CHANGE_CONFIGURATION";
public static final String CHANGE_NETWORK_STATE = "android.permission.CHANGE_NETWORK_STATE";
public static final String CHANGE_WIFI_MULTICAST_STATE =
"android.permission.CHANGE_WIFI_MULTICAST_STATE";
public static final String CHANGE_WIFI_STATE = "android.permission.CHANGE_WIFI_STATE";
public static final String CLEAR_APP_CACHE = "android.permission.CLEAR_APP_CACHE";
public static final String CONTROL_LOCATION_UPDATES =
"android.permission.CONTROL_LOCATION_UPDATES";
public static final String DELETE_CACHE_FILES = "android.permission.DELETE_CACHE_FILES";
public static final String DELETE_PACKAGES = "android.permission.DELETE_PACKAGES";
public static final String DELIVER_COMPANION_MESSAGES =
"android.permission.DELIVER_COMPANION_MESSAGES";
public static final String DIAGNOSTIC = "android.permission.DIAGNOSTIC";
public static final String DISABLE_KEYGUARD = "android.permission.DISABLE_KEYGUARD";
public static final String DUMP = "android.permission.DUMP";
public static final String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR";
public static final String FACTORY_TEST = "android.permission.FACTORY_TEST";
public static final String FOREGROUND_SERVICE = "android.permission.FOREGROUND_SERVICE";
public static final String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
public static final String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED";
public static final String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
public static final String GET_TASKS = "android.permission.GET_TASKS";
public static final String GLOBAL_SEARCH = "android.permission.GLOBAL_SEARCH";
public static final String HIDE_OVERLAY_WINDOWS = "android.permission.HIDE_OVERLAY_WINDOWS";
public static final String HIGH_SAMPLING_RATE_SENSORS =
"android.permission.HIGH_SAMPLING_RATE_SENSORS";
public static final String INSTALL_LOCATION_PROVIDER =
"android.permission.INSTALL_LOCATION_PROVIDER";
public static final String INSTALL_PACKAGES = "android.permission.INSTALL_PACKAGES";
public static final String INSTALL_SHORTCUT = "com.android.launcher.permission.INSTALL_SHORTCUT";
public static final String INSTANT_APP_FOREGROUND_SERVICE =
"android.permission.INSTANT_APP_FOREGROUND_SERVICE";
public static final String INTERACT_ACROSS_PROFILES =
"android.permission.INTERACT_ACROSS_PROFILES";
public static final String INTERNET = "android.permission.INTERNET";
public static final String KILL_BACKGROUND_PROCESSES =
"android.permission.KILL_BACKGROUND_PROCESSES";
public static final String LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK =
"android.permission.LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK";
public static final String LOADER_USAGE_STATS = "android.permission.LOADER_USAGE_STATS";
public static final String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
public static final String MANAGE_DOCUMENTS = "android.permission.MANAGE_DOCUMENTS";
public static final String MANAGE_EXTERNAL_STORAGE = "android.permission.MANAGE_EXTERNAL_STORAGE";
public static final String MANAGE_MEDIA = "android.permission.MANAGE_MEDIA";
public static final String MANAGE_ONGOING_CALLS = "android.permission.MANAGE_ONGOING_CALLS";
public static final String MANAGE_OWN_CALLS = "android.permission.MANAGE_OWN_CALLS";
public static final String MANAGE_WIFI_INTERFACES = "android.permission.MANAGE_WIFI_INTERFACES";
public static final String MANAGE_WIFI_NETWORK_SELECTION =
"android.permission.MANAGE_WIFI_NETWORK_SELECTION";
public static final String MASTER_CLEAR = "android.permission.MASTER_CLEAR";
public static final String MEDIA_CONTENT_CONTROL = "android.permission.MEDIA_CONTENT_CONTROL";
public static final String MODIFY_AUDIO_SETTINGS = "android.permission.MODIFY_AUDIO_SETTINGS";
public static final String MODIFY_PHONE_STATE = "android.permission.MODIFY_PHONE_STATE";
public static final String MOUNT_FORMAT_FILESYSTEMS =
"android.permission.MOUNT_FORMAT_FILESYSTEMS";
public static final String MOUNT_UNMOUNT_FILESYSTEMS =
"android.permission.MOUNT_UNMOUNT_FILESYSTEMS";
public static final String NEARBY_WIFI_DEVICES = "android.permission.NEARBY_WIFI_DEVICES";
public static final String NFC = "android.permission.NFC";
public static final String NFC_PREFERRED_PAYMENT_INFO =
"android.permission.NFC_PREFERRED_PAYMENT_INFO";
public static final String NFC_TRANSACTION_EVENT = "android.permission.NFC_TRANSACTION_EVENT";
public static final String OVERRIDE_WIFI_CONFIG = "android.permission.OVERRIDE_WIFI_CONFIG";
public static final String PACKAGE_USAGE_STATS = "android.permission.PACKAGE_USAGE_STATS";
public static final String PERSISTENT_ACTIVITY = "android.permission.PERSISTENT_ACTIVITY";
public static final String POST_NOTIFICATIONS = "android.permission.POST_NOTIFICATIONS";
public static final String PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS";
public static final String QUERY_ALL_PACKAGES = "android.permission.QUERY_ALL_PACKAGES";
public static final String READ_ASSISTANT_APP_SEARCH_DATA =
"android.permission.READ_ASSISTANT_APP_SEARCH_DATA";
public static final String READ_BASIC_PHONE_STATE = "android.permission.READ_BASIC_PHONE_STATE";
public static final String READ_CALENDAR = "android.permission.READ_CALENDAR";
public static final String READ_CALL_LOG = "android.permission.READ_CALL_LOG";
public static final String READ_CONTACTS = "android.permission.READ_CONTACTS";
public static final String READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE";
public static final String READ_HOME_APP_SEARCH_DATA =
"android.permission.READ_HOME_APP_SEARCH_DATA";
public static final String READ_INPUT_STATE = "android.permission.READ_INPUT_STATE";
public static final String READ_LOGS = "android.permission.READ_LOGS";
public static final String READ_MEDIA_AUDIO = "android.permission.READ_MEDIA_AUDIO";
public static final String READ_MEDIA_IMAGES = "android.permission.READ_MEDIA_IMAGES";
public static final String READ_MEDIA_VIDEO = "android.permission.READ_MEDIA_VIDEO";
public static final String READ_NEARBY_STREAMING_POLICY =
"android.permission.READ_NEARBY_STREAMING_POLICY";
public static final String READ_PHONE_NUMBERS = "android.permission.READ_PHONE_NUMBERS";
public static final String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
public static final String READ_PRECISE_PHONE_STATE =
"android.permission.READ_PRECISE_PHONE_STATE";
public static final String READ_SMS = "android.permission.READ_SMS";
public static final String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
public static final String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
public static final String READ_VOICEMAIL = "com.android.voicemail.permission.READ_VOICEMAIL";
public static final String REBOOT = "android.permission.REBOOT";
public static final String RECEIVE_BOOT_COMPLETED = "android.permission.RECEIVE_BOOT_COMPLETED";
public static final String RECEIVE_MMS = "android.permission.RECEIVE_MMS";
public static final String RECEIVE_SMS = "android.permission.RECEIVE_SMS";
public static final String RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH";
public static final String RECORD_AUDIO = "android.permission.RECORD_AUDIO";
public static final String REORDER_TASKS = "android.permission.REORDER_TASKS";
public static final String REQUEST_COMPANION_PROFILE_APP_STREAMING =
"android.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING";
public static final String REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION =
"android.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION";
public static final String REQUEST_COMPANION_PROFILE_COMPUTER =
"android.permission.REQUEST_COMPANION_PROFILE_COMPUTER";
public static final String REQUEST_COMPANION_PROFILE_WATCH =
"android.permission.REQUEST_COMPANION_PROFILE_WATCH";
public static final String REQUEST_COMPANION_RUN_IN_BACKGROUND =
"android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND";
public static final String REQUEST_COMPANION_SELF_MANAGED =
"android.permission.REQUEST_COMPANION_SELF_MANAGED";
public static final String REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND =
"android.permission.REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND";
public static final String REQUEST_COMPANION_USE_DATA_IN_BACKGROUND =
"android.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND";
public static final String REQUEST_DELETE_PACKAGES = "android.permission.REQUEST_DELETE_PACKAGES";
public static final String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS =
"android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
public static final String REQUEST_INSTALL_PACKAGES =
"android.permission.REQUEST_INSTALL_PACKAGES";
public static final String REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE =
"android.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE";
public static final String REQUEST_PASSWORD_COMPLEXITY =
"android.permission.REQUEST_PASSWORD_COMPLEXITY";
public static final String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
public static final String SCHEDULE_EXACT_ALARM = "android.permission.SCHEDULE_EXACT_ALARM";
public static final String SEND_RESPOND_VIA_MESSAGE =
"android.permission.SEND_RESPOND_VIA_MESSAGE";
public static final String SEND_SMS = "android.permission.SEND_SMS";
public static final String SET_ALARM = "com.android.alarm.permission.SET_ALARM";
public static final String SET_ALWAYS_FINISH = "android.permission.SET_ALWAYS_FINISH";
public static final String SET_ANIMATION_SCALE = "android.permission.SET_ANIMATION_SCALE";
public static final String SET_DEBUG_APP = "android.permission.SET_DEBUG_APP";
public static final String SET_PREFERRED_APPLICATIONS =
"android.permission.SET_PREFERRED_APPLICATIONS";
public static final String SET_PROCESS_LIMIT = "android.permission.SET_PROCESS_LIMIT";
public static final String SET_TIME = "android.permission.SET_TIME";
public static final String SET_TIME_ZONE = "android.permission.SET_TIME_ZONE";
public static final String SET_WALLPAPER = "android.permission.SET_WALLPAPER";
public static final String SET_WALLPAPER_HINTS = "android.permission.SET_WALLPAPER_HINTS";
public static final String SIGNAL_PERSISTENT_PROCESSES =
"android.permission.SIGNAL_PERSISTENT_PROCESSES";
public static final String SMS_FINANCIAL_TRANSACTIONS =
"android.permission.SMS_FINANCIAL_TRANSACTIONS";
public static final String START_FOREGROUND_SERVICES_FROM_BACKGROUND =
"android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND";
public static final String START_VIEW_APP_FEATURES = "android.permission.START_VIEW_APP_FEATURES";
public static final String START_VIEW_PERMISSION_USAGE =
"android.permission.START_VIEW_PERMISSION_USAGE";
public static final String STATUS_BAR = "android.permission.STATUS_BAR";
public static final String SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE =
"android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE";
public static final String SYSTEM_ALERT_WINDOW = "android.permission.SYSTEM_ALERT_WINDOW";
public static final String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
public static final String UNINSTALL_SHORTCUT =
"com.android.launcher.permission.UNINSTALL_SHORTCUT";
public static final String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
public static final String UPDATE_PACKAGES_WITHOUT_USER_ACTION =
"android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION";
public static final String USE_BIOMETRIC = "android.permission.USE_BIOMETRIC";
public static final String USE_EXACT_ALARM = "android.permission.USE_EXACT_ALARM";
public static final String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
public static final String USE_FULL_SCREEN_INTENT = "android.permission.USE_FULL_SCREEN_INTENT";
public static final String USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER =
"android.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER";
public static final String USE_SIP = "android.permission.USE_SIP";
public static final String UWB_RANGING = "android.permission.UWB_RANGING";
public static final String VIBRATE = "android.permission.VIBRATE";
public static final String WAKE_LOCK = "android.permission.WAKE_LOCK";
public static final String WRITE_APN_SETTINGS = "android.permission.WRITE_APN_SETTINGS";
public static final String WRITE_CALENDAR = "android.permission.WRITE_CALENDAR";
public static final String WRITE_CALL_LOG = "android.permission.WRITE_CALL_LOG";
public static final String WRITE_CONTACTS = "android.permission.WRITE_CONTACTS";
public static final String WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE";
public static final String WRITE_GSERVICES = "android.permission.WRITE_GSERVICES";
public static final String WRITE_SECURE_SETTINGS = "android.permission.WRITE_SECURE_SETTINGS";
public static final String WRITE_SETTINGS = "android.permission.WRITE_SETTINGS";
public static final String WRITE_SYNC_SETTINGS = "android.permission.WRITE_SYNC_SETTINGS";
public static final String WRITE_VOICEMAIL = "com.android.voicemail.permission.WRITE_VOICEMAIL";
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
public static final String GROUP_ACTIVITY_RECOGNITION =
"android.permission-group.ACTIVITY_RECOGNITION";
public static final String GROUP_CALENDAR = "android.permission-group.CALENDAR";
public static final String GROUP_CALL_LOG = "android.permission-group.CALL_LOG";
public static final String GROUP_CAMERA = "android.permission-group.CAMERA";
public static final String GROUP_CONTACTS = "android.permission-group.CONTACTS";
public static final String GROUP_LOCATION = "android.permission-group.LOCATION";
public static final String GROUP_MICROPHONE = "android.permission-group.MICROPHONE";
public static final String GROUP_NEARBY_DEVICES = "android.permission-group.NEARBY_DEVICES";
public static final String GROUP_NOTIFICATIONS = "android.permission-group.NOTIFICATIONS";
public static final String GROUP_PHONE = "android.permission-group.PHONE";
public static final String GROUP_READ_MEDIA_AURAL = "android.permission-group.READ_MEDIA_AURAL";
public static final String GROUP_READ_MEDIA_VISUAL = "android.permission-group.READ_MEDIA_VISUAL";
public static final String GROUP_SENSORS = "android.permission-group.SENSORS";
public static final String GROUP_SMS = "android.permission-group.SMS";
public static final String GROUP_STORAGE = "android.permission-group.STORAGE";
}
@@ -0,0 +1,234 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.permissions
/**
* Model for a permission entry.
*
* @property name The name of the permission as defined in the `android.Manifest.permission` class.
* @property constant The constant value of the permission.
* @author Akash Yadav
*/
enum class Permission constructor(val constant: String) {
ACCEPT_HANDOVER(ManifestPermissionConstants.ACCEPT_HANDOVER),
ACCESS_BACKGROUND_LOCATION(ManifestPermissionConstants.ACCESS_BACKGROUND_LOCATION),
ACCESS_BLOBS_ACROSS_USERS(ManifestPermissionConstants.ACCESS_BLOBS_ACROSS_USERS),
ACCESS_CHECKIN_PROPERTIES(ManifestPermissionConstants.ACCESS_CHECKIN_PROPERTIES),
ACCESS_COARSE_LOCATION(ManifestPermissionConstants.ACCESS_COARSE_LOCATION),
ACCESS_FINE_LOCATION(ManifestPermissionConstants.ACCESS_FINE_LOCATION),
ACCESS_LOCATION_EXTRA_COMMANDS(ManifestPermissionConstants.ACCESS_LOCATION_EXTRA_COMMANDS),
ACCESS_MEDIA_LOCATION(ManifestPermissionConstants.ACCESS_MEDIA_LOCATION),
ACCESS_NETWORK_STATE(ManifestPermissionConstants.ACCESS_NETWORK_STATE),
ACCESS_NOTIFICATION_POLICY(ManifestPermissionConstants.ACCESS_NOTIFICATION_POLICY),
ACCESS_WIFI_STATE(ManifestPermissionConstants.ACCESS_WIFI_STATE),
ACCOUNT_MANAGER(ManifestPermissionConstants.ACCOUNT_MANAGER),
ACTIVITY_RECOGNITION(ManifestPermissionConstants.ACTIVITY_RECOGNITION),
ADD_VOICEMAIL(ManifestPermissionConstants.ADD_VOICEMAIL),
ANSWER_PHONE_CALLS(ManifestPermissionConstants.ANSWER_PHONE_CALLS),
BATTERY_STATS(ManifestPermissionConstants.BATTERY_STATS),
BIND_ACCESSIBILITY_SERVICE(ManifestPermissionConstants.BIND_ACCESSIBILITY_SERVICE),
BIND_APPWIDGET(ManifestPermissionConstants.BIND_APPWIDGET),
BIND_AUTOFILL_SERVICE(ManifestPermissionConstants.BIND_AUTOFILL_SERVICE),
BIND_CALL_REDIRECTION_SERVICE(ManifestPermissionConstants.BIND_CALL_REDIRECTION_SERVICE),
BIND_CARRIER_MESSAGING_CLIENT_SERVICE(ManifestPermissionConstants.BIND_CARRIER_MESSAGING_CLIENT_SERVICE),
BIND_CARRIER_MESSAGING_SERVICE(ManifestPermissionConstants.BIND_CARRIER_MESSAGING_SERVICE),
BIND_CARRIER_SERVICES(ManifestPermissionConstants.BIND_CARRIER_SERVICES),
BIND_CHOOSER_TARGET_SERVICE(ManifestPermissionConstants.BIND_CHOOSER_TARGET_SERVICE),
BIND_COMPANION_DEVICE_SERVICE(ManifestPermissionConstants.BIND_COMPANION_DEVICE_SERVICE),
BIND_CONDITION_PROVIDER_SERVICE(ManifestPermissionConstants.BIND_CONDITION_PROVIDER_SERVICE),
BIND_CONTROLS(ManifestPermissionConstants.BIND_CONTROLS),
BIND_DEVICE_ADMIN(ManifestPermissionConstants.BIND_DEVICE_ADMIN),
BIND_DREAM_SERVICE(ManifestPermissionConstants.BIND_DREAM_SERVICE),
BIND_INCALL_SERVICE(ManifestPermissionConstants.BIND_INCALL_SERVICE),
BIND_INPUT_METHOD(ManifestPermissionConstants.BIND_INPUT_METHOD),
BIND_MIDI_DEVICE_SERVICE(ManifestPermissionConstants.BIND_MIDI_DEVICE_SERVICE),
BIND_NFC_SERVICE(ManifestPermissionConstants.BIND_NFC_SERVICE),
BIND_NOTIFICATION_LISTENER_SERVICE(ManifestPermissionConstants.BIND_NOTIFICATION_LISTENER_SERVICE),
BIND_PRINT_SERVICE(ManifestPermissionConstants.BIND_PRINT_SERVICE),
BIND_QUICK_ACCESS_WALLET_SERVICE(ManifestPermissionConstants.BIND_QUICK_ACCESS_WALLET_SERVICE),
BIND_QUICK_SETTINGS_TILE(ManifestPermissionConstants.BIND_QUICK_SETTINGS_TILE),
BIND_REMOTEVIEWS(ManifestPermissionConstants.BIND_REMOTEVIEWS),
BIND_SCREENING_SERVICE(ManifestPermissionConstants.BIND_SCREENING_SERVICE),
BIND_TELECOM_CONNECTION_SERVICE(ManifestPermissionConstants.BIND_TELECOM_CONNECTION_SERVICE),
BIND_TEXT_SERVICE(ManifestPermissionConstants.BIND_TEXT_SERVICE),
BIND_TV_INPUT(ManifestPermissionConstants.BIND_TV_INPUT),
BIND_TV_INTERACTIVE_APP(ManifestPermissionConstants.BIND_TV_INTERACTIVE_APP),
BIND_VISUAL_VOICEMAIL_SERVICE(ManifestPermissionConstants.BIND_VISUAL_VOICEMAIL_SERVICE),
BIND_VOICE_INTERACTION(ManifestPermissionConstants.BIND_VOICE_INTERACTION),
BIND_VPN_SERVICE(ManifestPermissionConstants.BIND_VPN_SERVICE),
BIND_VR_LISTENER_SERVICE(ManifestPermissionConstants.BIND_VR_LISTENER_SERVICE),
BIND_WALLPAPER(ManifestPermissionConstants.BIND_WALLPAPER),
BLUETOOTH(ManifestPermissionConstants.BLUETOOTH),
BLUETOOTH_ADMIN(ManifestPermissionConstants.BLUETOOTH_ADMIN),
BLUETOOTH_ADVERTISE(ManifestPermissionConstants.BLUETOOTH_ADVERTISE),
BLUETOOTH_CONNECT(ManifestPermissionConstants.BLUETOOTH_CONNECT),
BLUETOOTH_PRIVILEGED(ManifestPermissionConstants.BLUETOOTH_PRIVILEGED),
BLUETOOTH_SCAN(ManifestPermissionConstants.BLUETOOTH_SCAN),
BODY_SENSORS(ManifestPermissionConstants.BODY_SENSORS),
BODY_SENSORS_BACKGROUND(ManifestPermissionConstants.BODY_SENSORS_BACKGROUND),
BROADCAST_PACKAGE_REMOVED(ManifestPermissionConstants.BROADCAST_PACKAGE_REMOVED),
BROADCAST_SMS(ManifestPermissionConstants.BROADCAST_SMS),
BROADCAST_STICKY(ManifestPermissionConstants.BROADCAST_STICKY),
BROADCAST_WAP_PUSH(ManifestPermissionConstants.BROADCAST_WAP_PUSH),
CALL_COMPANION_APP(ManifestPermissionConstants.CALL_COMPANION_APP),
CALL_PHONE(ManifestPermissionConstants.CALL_PHONE),
CALL_PRIVILEGED(ManifestPermissionConstants.CALL_PRIVILEGED),
CAMERA(ManifestPermissionConstants.CAMERA),
CAPTURE_AUDIO_OUTPUT(ManifestPermissionConstants.CAPTURE_AUDIO_OUTPUT),
CHANGE_COMPONENT_ENABLED_STATE(ManifestPermissionConstants.CHANGE_COMPONENT_ENABLED_STATE),
CHANGE_CONFIGURATION(ManifestPermissionConstants.CHANGE_CONFIGURATION),
CHANGE_NETWORK_STATE(ManifestPermissionConstants.CHANGE_NETWORK_STATE),
CHANGE_WIFI_MULTICAST_STATE(ManifestPermissionConstants.CHANGE_WIFI_MULTICAST_STATE),
CHANGE_WIFI_STATE(ManifestPermissionConstants.CHANGE_WIFI_STATE),
CLEAR_APP_CACHE(ManifestPermissionConstants.CLEAR_APP_CACHE),
CONTROL_LOCATION_UPDATES(ManifestPermissionConstants.CONTROL_LOCATION_UPDATES),
DELETE_CACHE_FILES(ManifestPermissionConstants.DELETE_CACHE_FILES),
DELETE_PACKAGES(ManifestPermissionConstants.DELETE_PACKAGES),
DELIVER_COMPANION_MESSAGES(ManifestPermissionConstants.DELIVER_COMPANION_MESSAGES),
DIAGNOSTIC(ManifestPermissionConstants.DIAGNOSTIC),
DISABLE_KEYGUARD(ManifestPermissionConstants.DISABLE_KEYGUARD),
DUMP(ManifestPermissionConstants.DUMP),
EXPAND_STATUS_BAR(ManifestPermissionConstants.EXPAND_STATUS_BAR),
FACTORY_TEST(ManifestPermissionConstants.FACTORY_TEST),
FOREGROUND_SERVICE(ManifestPermissionConstants.FOREGROUND_SERVICE),
GET_ACCOUNTS(ManifestPermissionConstants.GET_ACCOUNTS),
GET_ACCOUNTS_PRIVILEGED(ManifestPermissionConstants.GET_ACCOUNTS_PRIVILEGED),
GET_PACKAGE_SIZE(ManifestPermissionConstants.GET_PACKAGE_SIZE),
GET_TASKS(ManifestPermissionConstants.GET_TASKS),
GLOBAL_SEARCH(ManifestPermissionConstants.GLOBAL_SEARCH),
HIDE_OVERLAY_WINDOWS(ManifestPermissionConstants.HIDE_OVERLAY_WINDOWS),
HIGH_SAMPLING_RATE_SENSORS(ManifestPermissionConstants.HIGH_SAMPLING_RATE_SENSORS),
INSTALL_LOCATION_PROVIDER(ManifestPermissionConstants.INSTALL_LOCATION_PROVIDER),
INSTALL_PACKAGES(ManifestPermissionConstants.INSTALL_PACKAGES),
INSTALL_SHORTCUT(ManifestPermissionConstants.INSTALL_SHORTCUT),
INSTANT_APP_FOREGROUND_SERVICE(ManifestPermissionConstants.INSTANT_APP_FOREGROUND_SERVICE),
INTERACT_ACROSS_PROFILES(ManifestPermissionConstants.INTERACT_ACROSS_PROFILES),
INTERNET(ManifestPermissionConstants.INTERNET),
KILL_BACKGROUND_PROCESSES(ManifestPermissionConstants.KILL_BACKGROUND_PROCESSES),
LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK(ManifestPermissionConstants.LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK),
LOADER_USAGE_STATS(ManifestPermissionConstants.LOADER_USAGE_STATS),
LOCATION_HARDWARE(ManifestPermissionConstants.LOCATION_HARDWARE),
MANAGE_DOCUMENTS(ManifestPermissionConstants.MANAGE_DOCUMENTS),
MANAGE_EXTERNAL_STORAGE(ManifestPermissionConstants.MANAGE_EXTERNAL_STORAGE),
MANAGE_MEDIA(ManifestPermissionConstants.MANAGE_MEDIA),
MANAGE_ONGOING_CALLS(ManifestPermissionConstants.MANAGE_ONGOING_CALLS),
MANAGE_OWN_CALLS(ManifestPermissionConstants.MANAGE_OWN_CALLS),
MANAGE_WIFI_INTERFACES(ManifestPermissionConstants.MANAGE_WIFI_INTERFACES),
MANAGE_WIFI_NETWORK_SELECTION(ManifestPermissionConstants.MANAGE_WIFI_NETWORK_SELECTION),
MASTER_CLEAR(ManifestPermissionConstants.MASTER_CLEAR),
MEDIA_CONTENT_CONTROL(ManifestPermissionConstants.MEDIA_CONTENT_CONTROL),
MODIFY_AUDIO_SETTINGS(ManifestPermissionConstants.MODIFY_AUDIO_SETTINGS),
MODIFY_PHONE_STATE(ManifestPermissionConstants.MODIFY_PHONE_STATE),
MOUNT_FORMAT_FILESYSTEMS(ManifestPermissionConstants.MOUNT_FORMAT_FILESYSTEMS),
MOUNT_UNMOUNT_FILESYSTEMS(ManifestPermissionConstants.MOUNT_UNMOUNT_FILESYSTEMS),
NEARBY_WIFI_DEVICES(ManifestPermissionConstants.NEARBY_WIFI_DEVICES),
NFC(ManifestPermissionConstants.NFC),
NFC_PREFERRED_PAYMENT_INFO(ManifestPermissionConstants.NFC_PREFERRED_PAYMENT_INFO),
NFC_TRANSACTION_EVENT(ManifestPermissionConstants.NFC_TRANSACTION_EVENT),
OVERRIDE_WIFI_CONFIG(ManifestPermissionConstants.OVERRIDE_WIFI_CONFIG),
PACKAGE_USAGE_STATS(ManifestPermissionConstants.PACKAGE_USAGE_STATS),
PERSISTENT_ACTIVITY(ManifestPermissionConstants.PERSISTENT_ACTIVITY),
POST_NOTIFICATIONS(ManifestPermissionConstants.POST_NOTIFICATIONS),
PROCESS_OUTGOING_CALLS(ManifestPermissionConstants.PROCESS_OUTGOING_CALLS),
QUERY_ALL_PACKAGES(ManifestPermissionConstants.QUERY_ALL_PACKAGES),
READ_ASSISTANT_APP_SEARCH_DATA(ManifestPermissionConstants.READ_ASSISTANT_APP_SEARCH_DATA),
READ_BASIC_PHONE_STATE(ManifestPermissionConstants.READ_BASIC_PHONE_STATE),
READ_CALENDAR(ManifestPermissionConstants.READ_CALENDAR),
READ_CALL_LOG(ManifestPermissionConstants.READ_CALL_LOG),
READ_CONTACTS(ManifestPermissionConstants.READ_CONTACTS),
READ_EXTERNAL_STORAGE(ManifestPermissionConstants.READ_EXTERNAL_STORAGE),
READ_HOME_APP_SEARCH_DATA(ManifestPermissionConstants.READ_HOME_APP_SEARCH_DATA),
READ_INPUT_STATE(ManifestPermissionConstants.READ_INPUT_STATE),
READ_LOGS(ManifestPermissionConstants.READ_LOGS),
READ_MEDIA_AUDIO(ManifestPermissionConstants.READ_MEDIA_AUDIO),
READ_MEDIA_IMAGES(ManifestPermissionConstants.READ_MEDIA_IMAGES),
READ_MEDIA_VIDEO(ManifestPermissionConstants.READ_MEDIA_VIDEO),
READ_NEARBY_STREAMING_POLICY(ManifestPermissionConstants.READ_NEARBY_STREAMING_POLICY),
READ_PHONE_NUMBERS(ManifestPermissionConstants.READ_PHONE_NUMBERS),
READ_PHONE_STATE(ManifestPermissionConstants.READ_PHONE_STATE),
READ_PRECISE_PHONE_STATE(ManifestPermissionConstants.READ_PRECISE_PHONE_STATE),
READ_SMS(ManifestPermissionConstants.READ_SMS),
READ_SYNC_SETTINGS(ManifestPermissionConstants.READ_SYNC_SETTINGS),
READ_SYNC_STATS(ManifestPermissionConstants.READ_SYNC_STATS),
READ_VOICEMAIL(ManifestPermissionConstants.READ_VOICEMAIL),
REBOOT(ManifestPermissionConstants.REBOOT),
RECEIVE_BOOT_COMPLETED(ManifestPermissionConstants.RECEIVE_BOOT_COMPLETED),
RECEIVE_MMS(ManifestPermissionConstants.RECEIVE_MMS),
RECEIVE_SMS(ManifestPermissionConstants.RECEIVE_SMS),
RECEIVE_WAP_PUSH(ManifestPermissionConstants.RECEIVE_WAP_PUSH),
RECORD_AUDIO(ManifestPermissionConstants.RECORD_AUDIO),
REORDER_TASKS(ManifestPermissionConstants.REORDER_TASKS),
REQUEST_COMPANION_PROFILE_APP_STREAMING(ManifestPermissionConstants.REQUEST_COMPANION_PROFILE_APP_STREAMING),
REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION(ManifestPermissionConstants.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION),
REQUEST_COMPANION_PROFILE_COMPUTER(ManifestPermissionConstants.REQUEST_COMPANION_PROFILE_COMPUTER),
REQUEST_COMPANION_PROFILE_WATCH(ManifestPermissionConstants.REQUEST_COMPANION_PROFILE_WATCH),
REQUEST_COMPANION_RUN_IN_BACKGROUND(ManifestPermissionConstants.REQUEST_COMPANION_RUN_IN_BACKGROUND),
REQUEST_COMPANION_SELF_MANAGED(ManifestPermissionConstants.REQUEST_COMPANION_SELF_MANAGED),
REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND(ManifestPermissionConstants.REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND),
REQUEST_COMPANION_USE_DATA_IN_BACKGROUND(ManifestPermissionConstants.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND),
REQUEST_DELETE_PACKAGES(ManifestPermissionConstants.REQUEST_DELETE_PACKAGES),
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS(ManifestPermissionConstants.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS),
REQUEST_INSTALL_PACKAGES(ManifestPermissionConstants.REQUEST_INSTALL_PACKAGES),
REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE(ManifestPermissionConstants.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE),
REQUEST_PASSWORD_COMPLEXITY(ManifestPermissionConstants.REQUEST_PASSWORD_COMPLEXITY),
RESTART_PACKAGES(ManifestPermissionConstants.RESTART_PACKAGES),
SCHEDULE_EXACT_ALARM(ManifestPermissionConstants.SCHEDULE_EXACT_ALARM),
SEND_RESPOND_VIA_MESSAGE(ManifestPermissionConstants.SEND_RESPOND_VIA_MESSAGE),
SEND_SMS(ManifestPermissionConstants.SEND_SMS),
SET_ALARM(ManifestPermissionConstants.SET_ALARM),
SET_ALWAYS_FINISH(ManifestPermissionConstants.SET_ALWAYS_FINISH),
SET_ANIMATION_SCALE(ManifestPermissionConstants.SET_ANIMATION_SCALE),
SET_DEBUG_APP(ManifestPermissionConstants.SET_DEBUG_APP),
SET_PREFERRED_APPLICATIONS(ManifestPermissionConstants.SET_PREFERRED_APPLICATIONS),
SET_PROCESS_LIMIT(ManifestPermissionConstants.SET_PROCESS_LIMIT),
SET_TIME(ManifestPermissionConstants.SET_TIME),
SET_TIME_ZONE(ManifestPermissionConstants.SET_TIME_ZONE),
SET_WALLPAPER(ManifestPermissionConstants.SET_WALLPAPER),
SET_WALLPAPER_HINTS(ManifestPermissionConstants.SET_WALLPAPER_HINTS),
SIGNAL_PERSISTENT_PROCESSES(ManifestPermissionConstants.SIGNAL_PERSISTENT_PROCESSES),
SMS_FINANCIAL_TRANSACTIONS(ManifestPermissionConstants.SMS_FINANCIAL_TRANSACTIONS),
START_FOREGROUND_SERVICES_FROM_BACKGROUND(ManifestPermissionConstants.START_FOREGROUND_SERVICES_FROM_BACKGROUND),
START_VIEW_APP_FEATURES(ManifestPermissionConstants.START_VIEW_APP_FEATURES),
START_VIEW_PERMISSION_USAGE(ManifestPermissionConstants.START_VIEW_PERMISSION_USAGE),
STATUS_BAR(ManifestPermissionConstants.STATUS_BAR),
SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE(ManifestPermissionConstants.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE),
SYSTEM_ALERT_WINDOW(ManifestPermissionConstants.SYSTEM_ALERT_WINDOW),
TRANSMIT_IR(ManifestPermissionConstants.TRANSMIT_IR),
UNINSTALL_SHORTCUT(ManifestPermissionConstants.UNINSTALL_SHORTCUT),
UPDATE_DEVICE_STATS(ManifestPermissionConstants.UPDATE_DEVICE_STATS),
UPDATE_PACKAGES_WITHOUT_USER_ACTION(ManifestPermissionConstants.UPDATE_PACKAGES_WITHOUT_USER_ACTION),
USE_BIOMETRIC(ManifestPermissionConstants.USE_BIOMETRIC),
USE_EXACT_ALARM(ManifestPermissionConstants.USE_EXACT_ALARM),
USE_FINGERPRINT(ManifestPermissionConstants.USE_FINGERPRINT),
USE_FULL_SCREEN_INTENT(ManifestPermissionConstants.USE_FULL_SCREEN_INTENT),
USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER(ManifestPermissionConstants.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER),
USE_SIP(ManifestPermissionConstants.USE_SIP),
UWB_RANGING(ManifestPermissionConstants.UWB_RANGING),
VIBRATE(ManifestPermissionConstants.VIBRATE),
WAKE_LOCK(ManifestPermissionConstants.WAKE_LOCK),
WRITE_APN_SETTINGS(ManifestPermissionConstants.WRITE_APN_SETTINGS),
WRITE_CALENDAR(ManifestPermissionConstants.WRITE_CALENDAR),
WRITE_CALL_LOG(ManifestPermissionConstants.WRITE_CALL_LOG),
WRITE_CONTACTS(ManifestPermissionConstants.WRITE_CONTACTS),
WRITE_EXTERNAL_STORAGE(ManifestPermissionConstants.WRITE_EXTERNAL_STORAGE),
WRITE_GSERVICES(ManifestPermissionConstants.WRITE_GSERVICES),
WRITE_SECURE_SETTINGS(ManifestPermissionConstants.WRITE_SECURE_SETTINGS),
WRITE_SETTINGS(ManifestPermissionConstants.WRITE_SETTINGS),
WRITE_SYNC_SETTINGS(ManifestPermissionConstants.WRITE_SYNC_SETTINGS),
WRITE_VOICEMAIL(ManifestPermissionConstants.WRITE_VOICEMAIL);
}
@@ -0,0 +1,42 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.permissions
/**
* Model for a permission group entry.
*
* @property constant The constant value of the permission group.
* @author Akash Yadav
*/
enum class PermissionGroup(val constant: String) {
ACTIVITY_RECOGNITION(ManifestPermissionConstants.GROUP_ACTIVITY_RECOGNITION),
CALENDAR(ManifestPermissionConstants.GROUP_CALENDAR),
CALL_LOG(ManifestPermissionConstants.GROUP_CALL_LOG),
CAMERA(ManifestPermissionConstants.GROUP_CAMERA),
CONTACTS(ManifestPermissionConstants.GROUP_CONTACTS),
LOCATION(ManifestPermissionConstants.GROUP_LOCATION),
MICROPHONE(ManifestPermissionConstants.GROUP_MICROPHONE),
NEARBY_DEVICES(ManifestPermissionConstants.GROUP_NEARBY_DEVICES),
NOTIFICATIONS(ManifestPermissionConstants.GROUP_NOTIFICATIONS),
PHONE(ManifestPermissionConstants.GROUP_PHONE),
READ_MEDIA_AURAL(ManifestPermissionConstants.GROUP_READ_MEDIA_AURAL),
READ_MEDIA_VISUAL(ManifestPermissionConstants.GROUP_READ_MEDIA_VISUAL),
SENSORS(ManifestPermissionConstants.GROUP_SENSORS),
SMS(ManifestPermissionConstants.GROUP_SMS),
STORAGE(ManifestPermissionConstants.GROUP_STORAGE)
}
@@ -0,0 +1,44 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.registry
import java.io.File
/**
* Base interface for all XML registry interfaces.
*
* @param T The type of data the registry provides.
* @author Akash Yadav
*/
interface XmlRegistry<T> {
/**
* Whether the actions should be logged.
*/
var isLoggingEnabled: Boolean
/**
* Get data for the given platform directory.
*
* @param platform The platform directory.
*/
fun forPlatformDir(platform: File): T?
/** Clears all the cached data. */
fun clear()
}
@@ -0,0 +1,94 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.resources
import com.android.aaptcompiler.ResourceGroup
import com.android.aaptcompiler.ResourceTable
import com.itsaky.androidide.lookup.Lookup
import com.itsaky.androidide.utils.ServiceLoader
import com.itsaky.androidide.xml.registry.XmlRegistry
import java.io.File
/**
* Handles resource tables for multiple modules/dependencies and the framework resources.
*
* @author Akash Yadav
*/
interface ResourceTableRegistry : XmlRegistry<ResourceTable> {
companion object {
const val PCK_ANDROID = "android"
@JvmStatic
val COMPLETION_MODULE_RES = Lookup.Key<Set<ResourceTable>>()
@JvmStatic
val COMPLETION_DEP_RES = Lookup.Key<Set<ResourceTable>>()
@JvmStatic
val COMPLETION_FRAMEWORK_RES = Lookup.Key<ResourceTable>()
@JvmStatic
val COMPLETION_MANIFEST_ATTR_RES = Lookup.Key<ResourceTable>()
private var sInstance: ResourceTableRegistry? = null
@JvmStatic
fun getInstance(): ResourceTableRegistry {
val klass = ResourceTableRegistry::class.java
return sInstance ?: ServiceLoader.load(klass, klass.classLoader).findFirstOrThrow().also { sInstance = it }
}
}
/**
* Find the resource table by package name. Should not be used for platform resource tables.
*
* @param name The package name for the resource table.
*/
fun forPackage(name: String, vararg resDirs: File): ResourceTable?
/**
* Remove the resource table entry for the given package name.
*
* @param packageName The package name to remove the resource table entry for.
*/
fun removeTable(packageName: String)
/**
* Get the resource group which corresponds to the attributes for `AndroidManifest.xml`.
*
* @return The [ResourceGroup] or null if not found or not available.
*/
fun getManifestAttrTable(platform: File): ResourceTable?
/** Get the list of all activity actions for the given [platform] directory. */
fun getActivityActions(platform: File): List<String>
/** Get the list of all broadcast actions for the given [platform] directory. */
fun getBroadcastActions(platform: File): List<String>
/** Get the list of all service actions for the given [platform] directory. */
fun getServiceActions(platform: File): List<String>
/** Get the list of all categories for the given [platform] directory. */
fun getCategories(platform: File): List<String>
/** Get the list of all features for the given [platform] directory. */
fun getFeatures(platform: File): List<String>
override fun forPlatformDir(platform: File): ResourceTable? {
return forPackage(PCK_ANDROID, File(platform, "data/res"))
}
}
@@ -0,0 +1,25 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.utils
import java.util.regex.Pattern
val attrValue_unqualifiedRef: Pattern by lazy { Pattern.compile("@(\\w+)/(.*)") }
val attrValue_qualifiedRef: Pattern by lazy { Pattern.compile("@((\\w|\\.)+):(\\w+)/(.*)") }
val attrValue_qualifiedRefWithIncompleteType: Pattern by lazy { Pattern.compile("@((\\w|\\.)+):(\\w*)") }
val attrValue_qualifiedRefWithIncompletePckOrType: Pattern by lazy { Pattern.compile("@((\\w|\\.)*)") }
@@ -0,0 +1,39 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.versions
import com.itsaky.androidide.lookup.Lookup
/**
* API information about classes.
*
* @author Akash Yadav
*/
interface ApiVersions {
companion object {
@JvmStatic val COMPLETION_LOOKUP_KEY = Lookup.Key<ApiVersions>()
}
/**
* Get the information about the class with the given name.
*
* @param name The fully qualified name of the class.
*/
fun getClass(name: String): ClassInfo?
}
@@ -0,0 +1,46 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.versions
import com.itsaky.androidide.utils.ServiceLoader
import com.itsaky.androidide.xml.registry.XmlRegistry
/**
* Registry that reads information about the API versions of classes, their fields and methods.
*
* The following information is stored :
* - Since
* - Removed
* - Deprecated
* @author Akash Yadav
*/
interface ApiVersionsRegistry : XmlRegistry<ApiVersions> {
companion object {
private var sInstance: ApiVersionsRegistry? = null
/** Get the default instance of [ApiVersionsRegistry]. */
@JvmStatic
fun getInstance(): ApiVersionsRegistry {
val klass = ApiVersionsRegistry::class.java
return sInstance ?: ServiceLoader.load(klass, klass.classLoader).findFirstOrThrow()
.also { sInstance = it }
}
}
}
@@ -0,0 +1,32 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.versions
/**
* Info about a class.
*
* @author Akash Yadav
*/
interface ClassInfo : Info {
/** Get info about the field with the given name. */
fun getField(name: String): FieldInfo?
/** Get the method with the given [name] and the [parameterTypes]. */
fun getMethod(name: String, vararg params: String) : MethodInfo?
}
@@ -0,0 +1,25 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.versions
/**
* Info about a field.
*
* @author Akash Yadav
*/
interface FieldInfo : Info
@@ -0,0 +1,38 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.versions
/**
* Base class for info about class, fields and methods.
*
* @author Akash Yadav
*/
interface Info {
/** Name of this element. */
val name: String
/** The introducing API version. */
val since: Int
/** The removing API version. */
val removed: Int
/** The deprecating API version. */
val deprecated: Int
}
@@ -0,0 +1,32 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.versions
/**
* Info about a method.
*
* @author Akash Yadav
*/
interface MethodInfo : Info {
/**
* In case of a method, the [Info.name] contains signature of the method This field contains the
* actual simple name
*/
val simpleName: String
}
@@ -0,0 +1,37 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.widgets
/**
* A widget defined in the `widgets.txt` file in the Android SDK.
*
* @author Akash Yadav
*/
interface Widget {
/** The simple name of the widget. For example, `TextView`. */
val simpleName: String
/** The qualified name of the widget. For example, `android.widget.TextView`. */
val qualifiedName: String
/** The type of widget. */
val type: WidgetType
/** The fully qualified names of the superclasses of this widget. */
val superclasses: List<String>
}
@@ -0,0 +1,52 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.widgets
import com.itsaky.androidide.lookup.Lookup
/**
* A widget table holds information about all widgets defined in the `widgets.txt`.
*
* @author Akash Yadav
*/
interface WidgetTable {
companion object {
@JvmStatic val COMPLETION_LOOKUP_KEY = Lookup.Key<WidgetTable>()
}
/**
* Get the widget for the given fully qualified name. For example, `android.widget.TextView`.
*
* @return The widget or `null`.
*/
fun getWidget(name: String): Widget?
/**
* Finds the first widget with the given simple name. This searches the whole table so [getWidget]
* is preferable.
*/
fun findWidgetWithSimpleName(name: String): Widget?
/**
* Get the set of all registered widgets.
*
* @return The set of widgets.
*/
fun getAllWidgets(): Set<Widget>
}
@@ -0,0 +1,43 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.widgets
import com.itsaky.androidide.utils.ServiceLoader
import com.itsaky.androidide.xml.registry.XmlRegistry
/**
* Information about widgets, layouts and layout params extracted from `widgets.txt` from the
* Android SDK.
*
* @author Akash Yadav
*/
interface WidgetTableRegistry : XmlRegistry<WidgetTable> {
companion object {
private var sInstance: WidgetTableRegistry? = null
/** Get the default instance of [WidgetTableRegistry]. */
@JvmStatic
fun getInstance(): WidgetTableRegistry {
val klass = WidgetTableRegistry::class.java
return sInstance ?: ServiceLoader.load(klass, klass.classLoader).findFirstOrThrow()
.also { sInstance = it }
}
}
}
@@ -0,0 +1,48 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.widgets
/**
* The type of [Widget].
*
* @author Akash Yadav
*/
enum class WidgetType(internal val c: Char) {
/** A widget. */
WIDGET('W'),
/** A layout (ViewGroup). */
LAYOUT('L'),
/** A layout param. */
LAYOUT_PARAM('P');
internal class Factory {
companion object {
@JvmStatic
fun forChar(c: Char): WidgetType? {
for (value in values()) {
if (value.c == c) {
return value
}
}
return null
}
}
}
}
@@ -0,0 +1,210 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.resources
import android.graphics.Color
import com.android.aaptcompiler.AaptResourceType.ATTR
import com.android.aaptcompiler.AaptResourceType.COLOR
import com.android.aaptcompiler.AaptResourceType.STRING
import com.android.aaptcompiler.AaptResourceType.STYLEABLE
import com.android.aaptcompiler.BasicString
import com.android.aaptcompiler.BinaryPrimitive
import com.android.aaptcompiler.ResourceName
import com.android.aaptcompiler.android.ResValue.DataType
import com.google.common.truth.Truth.assertThat
import com.itsaky.androidide.xml.findAndroidJar
import com.itsaky.androidide.xml.internal.resources.DefaultResourceTableRegistry
import com.itsaky.androidide.xml.resources.ResourceTableRegistry.Companion.PCK_ANDROID
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import java.io.File
/** @author Akash Yadav */
@RunWith(RobolectricTestRunner::class)
class ResourceTableRegistryTest {
@Test
fun `test instance of registry`() {
val instance = ResourceTableRegistry.getInstance()
assertThat(instance).isInstanceOf(DefaultResourceTableRegistry::class.java)
}
@Test
fun `test with simple framework resource parsing`() {
val androidJar = findAndroidJar()
val platform = androidJar.parentFile!!
val registry = ResourceTableRegistry.getInstance()
val resDir = File(androidJar.parentFile, "data/res")
val resourceTable = registry.forPackage(PCK_ANDROID, resDir)
assertThat(resourceTable).isNotNull()
// Should return same instance unless updated
assertThat(registry.forPackage(PCK_ANDROID, resDir)).isEqualTo(resourceTable)
// It should also create the manifest attrs table by default
registry.getManifestAttrTable(platform = platform).apply {
assertThat(this).isNotNull()
assertThat(this!!.packages).hasSize(1)
assertThat(this.packages.first().name).isEqualTo(PCK_ANDROID)
assertThat(findPackage(PCK_ANDROID)!!.findGroup(ATTR)).isNotNull()
assertThat(findPackage(PCK_ANDROID)!!.findGroup(STYLEABLE)).isNotNull()
}
registry.getActivityActions(platform).apply {
assertThat(this).isNotEmpty()
assertThat(this)
.containsAtLeastElementsIn(
arrayOf(
"android.app.action.SET_NEW_PASSWORD",
"android.app.action.START_ENCRYPTION",
"android.intent.action.CARRIER_SETUP",
"android.intent.action.CHOOSER",
"android.intent.action.MAIN",
"android.intent.action.MANAGE_APP_PERMISSION",
"android.intent.action.MANAGE_APP_PERMISSIONS"
)
)
assertThat(this.size).isGreaterThan(250) // actual size is 300+
}
registry.getBroadcastActions(platform).apply {
assertThat(this).isNotEmpty()
assertThat(this)
.containsAtLeastElementsIn(
arrayOf(
"android.telephony.action.SUBSCRIPTION_PLANS_CHANGED",
"android.telephony.action.SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED",
"android.telephony.euicc.action.NOTIFY_CARRIER_SETUP_INCOMPLETE",
"android.telephony.euicc.action.OTA_STATUS_CHANGED",
"android.app.action.USER_ADDED",
"android.app.action.USER_REMOVED"
)
)
}
registry.getServiceActions(platform).apply {
assertThat(this).isNotEmpty()
assertThat(this)
.containsAtLeastElementsIn(
arrayOf(
"android.telephony.data.DataService",
"android.view.InputMethod",
"android.intent.action.TTS_SERVICE",
"android.media.MediaRoute2ProviderService",
"android.service.voice.VoiceInteractionService",
"android.service.vr.VrListenerService"
)
)
}
registry.getCategories(platform).apply {
assertThat(this).isNotEmpty()
assertThat(this)
.containsAtLeastElementsIn(
arrayOf(
"android.intent.category.HOME",
"android.intent.category.HOME_MAIN",
"android.intent.category.INFO",
"android.intent.category.LAUNCHER",
"android.intent.category.LAUNCHER_APP",
"android.net.category.EVENT_IKE_ERROR",
"android.net.category.EVENT_NETWORK_ERROR",
"android.service.quicksettings.action.QS_TILE_PREFERENCES"
)
)
}
registry.getFeatures(platform).apply {
assertThat(this).isNotEmpty()
assertThat(this)
.containsAtLeastElementsIn(
arrayOf(
"android.software.vulkan.deqp.level",
"android.software.webview",
"android.software.window_magnification",
"android.sofware.nfc.beam",
"android.hardware.strongbox_keystore",
"android.hardware.telephony",
"android.hardware.telephony.calling",
"android.hardware.telephony.carrierlock",
"android.hardware.ethernet",
"android.hardware.faketouch"
)
)
}
resourceTable.apply {
assertThat(this).isNotNull()
assertThat(this!!.packages).hasSize(1)
this.packages.first().apply { assertThat(this.name).isEqualTo("android") }
}
resourceTable!!.findResource(ResourceName(pck = "android", type = STRING, entry = "ok")).apply {
assertThat(this).isNotNull()
assertThat(this!!.entry).isNotNull()
assertThat(this.entry.values).isNotEmpty()
this.entry.values.firstOrNull().apply {
assertThat(this).isNotNull()
assertThat(this!!.value).isNotNull()
this.value.apply {
assertThat(this).isInstanceOf(BasicString::class.java)
assertThat(this.toString()).isEqualTo("OK")
}
}
}
resourceTable
.findResource(ResourceName(pck = "android", type = STRING, entry = "cancel"))
.apply {
assertThat(this).isNotNull()
assertThat(this!!.entry).isNotNull()
assertThat(this.entry.values).isNotEmpty()
this.entry.values.firstOrNull().apply {
assertThat(this).isNotNull()
assertThat(this!!.value).isNotNull()
this.value.apply {
assertThat(this).isInstanceOf(BasicString::class.java)
assertThat(this.toString()).isEqualTo("Cancel")
}
}
}
resourceTable
.findResource(ResourceName(pck = "android", type = COLOR, entry = "holo_red_dark"))
.apply {
assertThat(this).isNotNull()
assertThat(this!!.entry).isNotNull()
assertThat(this.entry.values).isNotEmpty()
this.entry.values.firstOrNull().apply {
assertThat(this).isNotNull()
assertThat(this!!.value).isNotNull()
this.value.apply {
assertThat(this).isNotNull()
assertThat(this!!).isInstanceOf(BinaryPrimitive::class.java)
(this as BinaryPrimitive).resValue.apply {
assertThat(this).isNotNull()
assertThat(this.dataType).isEqualTo(DataType.INT_COLOR_ARGB8)
assertThat(this.data)
.isEqualTo(Color.parseColor(/*from colors_holo.xml*/ "#ffcc0000"))
}
}
}
}
}
}
@@ -0,0 +1,54 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml
import java.io.File
fun findAndroidJar(): File {
val androidHome = findAndroidHome()
return run {
for (platform in intArrayOf(33, 32, 31)) {
val f = File(androidHome, "platforms/android-$platform/android.jar")
if (f.exists() && !f.isDirectory) {
return@run f
}
}
throw RuntimeException("Cannot find android.jar")
}
}
fun findAndroidHome(): String {
var androidHome = System.getenv("ANDROID_HOME")
if (androidHome != null && androidHome.isNotBlank()) {
return androidHome
}
androidHome = System.getenv("ANDROID_SDK_ROOT")
if (androidHome != null && androidHome.isNotBlank()) {
return androidHome
}
val os = System.getProperty("os.name")!!
val home = System.getProperty("user.home")!!
return if (os.contains("Linux")) {
"$home/Android/Sdk"
} else {
"$home\\AppData\\Local\\Android\\Sdk"
}
}
@@ -0,0 +1,87 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.versions
import com.google.common.truth.Truth.assertThat
import com.itsaky.androidide.xml.findAndroidJar
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
/** @author Akash Yadav */
@RunWith(RobolectricTestRunner::class)
class ApiVersionsRegistryTest {
@Test
fun test() {
val androidJar = findAndroidJar()
val registry = ApiVersionsRegistry.getInstance()
val versions = registry.forPlatformDir(androidJar.parentFile!!)
assertThat(versions).isNotNull()
versions!!.getClass("android.Manifest\$permission").apply {
assertThat(this).isNotNull()
this!!.getField("WRITE_EXTERNAL_STORAGE").apply {
assertThat(this).isNotNull()
assertThat(this!!.since).isEqualTo(4)
assertThat(this.removed).isEqualTo(-1)
assertThat(this.deprecated).isEqualTo(-1)
}
this.getField("USE_BIOMETRIC").apply {
assertThat(this).isNotNull()
assertThat(this!!.since).isEqualTo(28)
assertThat(this.removed).isEqualTo(-1)
assertThat(this.deprecated).isEqualTo(-1)
}
this.getField("PERSISTENT_ACTIVITY").apply {
assertThat(this).isNotNull()
assertThat(this!!.since).isEqualTo(-1)
assertThat(this.removed).isEqualTo(-1)
assertThat(this.deprecated).isEqualTo(15)
}
this.getMethod("nonExistentMethod", "i.do.not.exist").apply { assertThat(this).isNull() }
this.getField("nonExistentField").apply { assertThat(this).isNull() }
}
versions.getClass("android.view.View").apply {
assertThat(this).isNotNull()
this!!.getField("SYSTEM_UI_FLAG_FULLSCREEN").apply {
assertThat(this).isNotNull()
assertThat(this!!.since).isEqualTo(16)
assertThat(this.removed).isEqualTo(-1)
assertThat(this.deprecated).isEqualTo(30)
}
this.getMethod(
"setOnSystemUiVisibilityChangeListener",
"android.view.View\$OnSystemUiVisibilityChangeListener"
)
.apply {
assertThat(this).isNotNull()
assertThat(this!!.since).isEqualTo(11)
assertThat(this.removed).isEqualTo(-1)
assertThat(this.deprecated).isEqualTo(30)
}
this.getMethod("nonExistentMethod", "i.do.not.exist").apply { assertThat(this).isNull() }
}
}
}
@@ -0,0 +1,94 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.xml.widgets
import com.google.common.truth.Truth.assertThat
import com.itsaky.androidide.xml.findAndroidJar
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import java.io.File
/** @author Akash Yadav */
@RunWith(RobolectricTestRunner::class)
class WidgetTableRegistryTest {
@Test
fun `test multiple calls should returns same instance`() {
val (platformDir, registry, table) = createTable()
assertThat(registry.forPlatformDir(platformDir)).isEqualTo(table)
}
@Test
fun `test simple layout retrieval`() {
val (_, _, table) = createTable()
table.getWidget("android.widget.FrameLayout").apply {
assertThat(this).isNotNull()
assertThat(this!!.qualifiedName).isEqualTo("android.widget.FrameLayout")
assertThat(this.simpleName).isEqualTo("FrameLayout")
assertThat(this.type).isEqualTo(WidgetType.LAYOUT)
}
}
@Test
fun `test table contains layout params`() {
val (_, _, table) = createTable()
table.getWidget("android.widget.FrameLayout.LayoutParams").apply {
assertThat(this).isNotNull()
assertThat(this!!.qualifiedName).isEqualTo("android.widget.FrameLayout.LayoutParams")
assertThat(this.simpleName).isEqualTo("LayoutParams")
assertThat(this.type).isEqualTo(WidgetType.LAYOUT_PARAM)
}
}
@Test
fun `test find with simple name`() {
val (_, _, table) = createTable()
table.findWidgetWithSimpleName("TextView").apply {
assertThat(this).isNotNull()
assertThat(this!!.simpleName).isEqualTo("TextView")
assertThat(this.qualifiedName).isEqualTo("android.widget.TextView")
assertThat(this.superclasses).containsExactly("android.view.View", "java.lang.Object")
}
}
@Test
fun `test get all widgets list`() {
val (_, _, table) = createTable()
assertThat(table.getAllWidgets().map(Widget::simpleName))
.containsAtLeast(
"TextView",
"ImageView",
"Button",
"LinearLayout",
"RelativeLayout",
"FrameLayout",
"GestureOverlayView",
"CalendarView"
)
}
private fun createTable(): Triple<File, WidgetTableRegistry, WidgetTable> {
val platformDir = findAndroidJar().parentFile!!
val registry = WidgetTableRegistry.getInstance()
val table = registry.forPlatformDir(platformDir)
assertThat(table).isNotNull()
return Triple(platformDir, registry, table!!)
}
}