111 lines
4.0 KiB
Kotlin
111 lines
4.0 KiB
Kotlin
package org.fdroid.index.v1
|
|
|
|
import android.content.pm.PackageInfo
|
|
import android.content.pm.PackageManager
|
|
import android.content.pm.PackageManager.GET_PERMISSIONS
|
|
import android.content.pm.PackageManager.GET_SIGNATURES
|
|
import android.os.Build.VERSION.SDK_INT
|
|
import androidx.core.content.pm.PackageInfoCompat
|
|
import kotlinx.serialization.ExperimentalSerializationApi
|
|
import kotlinx.serialization.json.encodeToStream
|
|
import org.fdroid.index.IndexCreator
|
|
import org.fdroid.index.IndexParser
|
|
import org.fdroid.index.IndexUtils.getPackageSigner
|
|
import org.fdroid.index.IndexUtils.getsig
|
|
import java.io.File
|
|
import java.io.IOException
|
|
|
|
/**
|
|
* Creates a deprecated V1 index from the given [packageNames]
|
|
* with information obtained from the [PackageManager].
|
|
*
|
|
* Attention: While [createRepo] creates `index-v1.json`,
|
|
* it does **not** create a signed `index-v1.jar`.
|
|
* The caller needs to handle this last signing step themselves.
|
|
*/
|
|
public class IndexV1Creator(
|
|
packageManager: PackageManager,
|
|
repoDir: File,
|
|
packageNames: Set<String>,
|
|
private val repo: RepoV1,
|
|
) : IndexCreator<IndexV1>(packageManager, repoDir, packageNames) {
|
|
|
|
@Throws(IOException::class)
|
|
@OptIn(ExperimentalSerializationApi::class)
|
|
public override fun createRepo(): IndexV1 {
|
|
prepareIconFolders()
|
|
val index = createIndex()
|
|
val indexJsonFile = File(repoDir, DATA_FILE_NAME)
|
|
indexJsonFile.outputStream().use { outputStream ->
|
|
IndexParser.json.encodeToStream(index, outputStream)
|
|
}
|
|
return index
|
|
}
|
|
|
|
private fun createIndex(): IndexV1 {
|
|
val apps = ArrayList<AppV1>(packageNames.size)
|
|
val packages = HashMap<String, List<PackageV1>>(packageNames.size)
|
|
for (packageName in packageNames) {
|
|
addApp(packageName, apps, packages)
|
|
}
|
|
return IndexV1(
|
|
repo = repo,
|
|
apps = apps,
|
|
packages = packages,
|
|
)
|
|
}
|
|
|
|
private fun addApp(
|
|
packageName: String,
|
|
apps: ArrayList<AppV1>,
|
|
packages: HashMap<String, List<PackageV1>>,
|
|
) {
|
|
@Suppress("DEPRECATION")
|
|
val flags = GET_SIGNATURES or GET_PERMISSIONS
|
|
|
|
@Suppress("PackageManagerGetSignatures")
|
|
val packageInfo = packageManager.getPackageInfo(packageName, flags)
|
|
apps.add(getApp(packageInfo))
|
|
packages[packageName] = listOf(getPackage(packageInfo))
|
|
}
|
|
|
|
private fun getApp(packageInfo: PackageInfo): AppV1 {
|
|
val icon = copyIconToRepo(packageInfo)
|
|
return AppV1(
|
|
packageName = packageInfo.packageName,
|
|
name = packageInfo.applicationInfo.loadLabel(packageManager).toString(),
|
|
license = "Unknown",
|
|
icon = icon,
|
|
)
|
|
}
|
|
|
|
private fun getPackage(packageInfo: PackageInfo): PackageV1 {
|
|
val apk = copyApkToRepo(packageInfo)
|
|
val hash = hashFile(apk)
|
|
val apkName = apk.name
|
|
val sig = getsig(packageInfo.signatures[0].toByteArray())
|
|
val signer = getPackageSigner(packageInfo.signatures[0].toByteArray())
|
|
return PackageV1(
|
|
packageName = packageInfo.packageName,
|
|
versionCode = PackageInfoCompat.getLongVersionCode(packageInfo),
|
|
versionName = packageInfo.versionName ?: PackageInfoCompat.getLongVersionCode(
|
|
packageInfo
|
|
).toString(),
|
|
apkName = apkName,
|
|
hash = hash,
|
|
hashType = "sha256",
|
|
sig = sig,
|
|
signer = signer,
|
|
size = File(packageInfo.applicationInfo.publicSourceDir).length(),
|
|
minSdkVersion = if (SDK_INT >= 24) packageInfo.applicationInfo.minSdkVersion else null,
|
|
targetSdkVersion = packageInfo.applicationInfo.targetSdkVersion,
|
|
usesPermission = packageInfo.requestedPermissions?.map {
|
|
PermissionV1(it)
|
|
} ?: emptyList(),
|
|
usesPermission23 = emptyList(),
|
|
nativeCode = parseNativeCode(packageInfo),
|
|
features = packageInfo.reqFeatures?.map { it.name } ?: emptyList(),
|
|
)
|
|
}
|
|
}
|