mirror of
https://github.com/tachiyomiorg/tachiyomi-extensions-inspector.git
synced 2024-12-24 15:51:49 +01:00
android support! thanks to TachiWeb devs.
This commit is contained in:
parent
ced07d4e1e
commit
1e46a0c78c
4
AndroidCompat/Config/build.gradle
Normal file
4
AndroidCompat/Config/build.gradle
Normal file
@ -0,0 +1,4 @@
|
||||
dependencies {
|
||||
// Config API
|
||||
// implementation("com.typesafe:config:1.4.0")
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package xyz.nulldev.ts.config
|
||||
|
||||
import org.kodein.di.DI
|
||||
import org.kodein.di.bind
|
||||
import org.kodein.di.singleton
|
||||
|
||||
class ConfigKodeinModule {
|
||||
fun create() = DI.Module("ConfigManager") {
|
||||
//Config module
|
||||
bind<ConfigManager>() with singleton { GlobalConfigManager }
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package xyz.nulldev.ts.config
|
||||
|
||||
import com.typesafe.config.Config
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import com.typesafe.config.ConfigRenderOptions
|
||||
import mu.KotlinLogging
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Manages app config.
|
||||
*/
|
||||
open class ConfigManager {
|
||||
private val generatedModules
|
||||
= mutableMapOf<Class<out ConfigModule>, ConfigModule>()
|
||||
val config by lazy { loadConfigs() }
|
||||
|
||||
//Public read-only view of modules
|
||||
val loadedModules: Map<Class<out ConfigModule>, ConfigModule>
|
||||
get() = generatedModules
|
||||
|
||||
open val configFolder: String
|
||||
get() = System.getProperty("compat-configdirs") ?: "tachiserver-data/config"
|
||||
|
||||
val logger = KotlinLogging.logger {}
|
||||
|
||||
/**
|
||||
* Get a config module
|
||||
*/
|
||||
inline fun <reified T : ConfigModule> module(): T
|
||||
= loadedModules[T::class.java] as T
|
||||
|
||||
/**
|
||||
* Get a config module (Java API)
|
||||
*/
|
||||
fun <T : ConfigModule> module(type: Class<T>): T
|
||||
= loadedModules[type] as T
|
||||
|
||||
/**
|
||||
* Load configs
|
||||
*/
|
||||
fun loadConfigs(): Config {
|
||||
val configs = mutableListOf<Config>()
|
||||
|
||||
//Load reference config
|
||||
configs += ConfigFactory.parseResources("reference.conf")
|
||||
|
||||
//Load custom configs from dir
|
||||
File(configFolder).listFiles()?.map {
|
||||
ConfigFactory.parseFile(it)
|
||||
}?.filterNotNull()?.forEach {
|
||||
configs += it.withFallback(configs.last())
|
||||
}
|
||||
|
||||
val config = configs.last().resolve()
|
||||
|
||||
logger.debug {
|
||||
"Loaded config:\n" + config.root().render(ConfigRenderOptions.concise().setFormatted(true))
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
fun registerModule(module: ConfigModule) {
|
||||
generatedModules.put(module.javaClass, module)
|
||||
}
|
||||
|
||||
fun registerModules(vararg modules: ConfigModule) {
|
||||
modules.forEach {
|
||||
registerModule(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object GlobalConfigManager : ConfigManager()
|
@ -0,0 +1,8 @@
|
||||
package xyz.nulldev.ts.config
|
||||
|
||||
import com.typesafe.config.Config
|
||||
|
||||
/**
|
||||
* Abstract config module.
|
||||
*/
|
||||
abstract class ConfigModule(config: Config)
|
@ -0,0 +1,35 @@
|
||||
package xyz.nulldev.ts.config
|
||||
|
||||
import com.typesafe.config.Config
|
||||
import java.io.File
|
||||
|
||||
class ServerConfig(config: Config) : ConfigModule(config) {
|
||||
val ip = config.getString("ip")
|
||||
val port = config.getInt("port")
|
||||
|
||||
val allowConfigChanges = config.getBoolean("allowConfigChanges")
|
||||
val enableWebUi = config.getBoolean("enableWebUi")
|
||||
val useOldWebUi = config.getBoolean("useOldWebUi")
|
||||
val prettyPrintApi = config.getBoolean("prettyPrintApi")
|
||||
// TODO Apply to operation IDs
|
||||
val disabledApiEndpoints = config.getStringList("disabledApiEndpoints").map(String::toLowerCase)
|
||||
val enabledApiEndpoints = config.getStringList("enabledApiEndpoints").map(String::toLowerCase)
|
||||
val httpInitializedPrintMessage = config.getString("httpInitializedPrintMessage")
|
||||
|
||||
val useExternalStaticFiles = config.getBoolean("useExternalStaticFiles")
|
||||
val externalStaticFilesFolder = config.getString("externalStaticFilesFolder")
|
||||
|
||||
val rootDir = registerFile(config.getString("rootDir"))
|
||||
val patchesDir = registerFile(config.getString("patchesDir"))
|
||||
|
||||
fun registerFile(file: String): File {
|
||||
return File(file).apply {
|
||||
mkdirs()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun register(config: Config)
|
||||
= ServerConfig(config.getConfig("ts.server"))
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package xyz.nulldev.ts.config.util
|
||||
|
||||
import com.typesafe.config.Config
|
||||
|
||||
operator fun Config.get(key: String) = getString(key)
|
||||
?: throw IllegalStateException("Could not find value for config entry: $key!")
|
@ -0,0 +1 @@
|
||||
xyz.nulldev.ts.api.v2.java.impl.ServerAPIImpl
|
BIN
AndroidCompat/Config/src/main/resources/al.png
Normal file
BIN
AndroidCompat/Config/src/main/resources/al.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
BIN
AndroidCompat/Config/src/main/resources/kitsu.png
Normal file
BIN
AndroidCompat/Config/src/main/resources/kitsu.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.9 KiB |
BIN
AndroidCompat/Config/src/main/resources/mal.png
Normal file
BIN
AndroidCompat/Config/src/main/resources/mal.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
4291
AndroidCompat/Config/src/main/resources/openapi.json
Normal file
4291
AndroidCompat/Config/src/main/resources/openapi.json
Normal file
File diff suppressed because one or more lines are too long
22
AndroidCompat/Config/src/main/resources/pref-schema.json
Normal file
22
AndroidCompat/Config/src/main/resources/pref-schema.json
Normal file
@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"label": "Sync",
|
||||
"icon": "import_export",
|
||||
"type": "nested",
|
||||
"prefs": []
|
||||
},
|
||||
{
|
||||
"label": "Server",
|
||||
"icon": "dns",
|
||||
"type": "nested",
|
||||
"prefs": [
|
||||
{
|
||||
"label": "Password authentication",
|
||||
"type": "text-password",
|
||||
"default": "",
|
||||
"key": "pref_ts_server_password",
|
||||
"hint": "Enter a password"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
87
AndroidCompat/Config/src/main/resources/reference.conf
Normal file
87
AndroidCompat/Config/src/main/resources/reference.conf
Normal file
@ -0,0 +1,87 @@
|
||||
# Server ip and port bindings
|
||||
ts.server.ip = 0.0.0.0
|
||||
ts.server.port = 4567
|
||||
|
||||
# Allow/disallow preference changes (useful for demos)
|
||||
ts.server.allowConfigChanges = true
|
||||
|
||||
# Enable the WebUI? Note: The API and multi-user sync server ui will remain available even if the WebUI is disabled
|
||||
ts.server.enableWebUi = true
|
||||
|
||||
# 'true' to use the old, buggy/memory-leaking WebUI
|
||||
ts.server.useOldWebUi = false
|
||||
|
||||
# 'true' to pretty print all JSON API responses
|
||||
ts.server.prettyPrintApi = false
|
||||
|
||||
# List of blacklisted/whitelisted API endpoints/operation IDs
|
||||
ts.server.disabledApiEndpoints = []
|
||||
ts.server.enabledApiEndpoints = []
|
||||
|
||||
# Message to print in the console when the API has finished booting
|
||||
ts.server.httpInitializedPrintMessage = ""
|
||||
|
||||
# Use external folder for static files
|
||||
ts.server.useExternalStaticFiles = false
|
||||
ts.server.externalStaticFilesFolder = ""
|
||||
|
||||
# Root storage dir
|
||||
ts.server.rootDir = tachiserver-data
|
||||
# Dir to store JVM patches
|
||||
ts.server.patchesDir = ${ts.server.rootDir}/patches
|
||||
|
||||
# Storage dir for the emulated Android app
|
||||
android.files.rootDir = ${ts.server.rootDir}/android-compat/appdata
|
||||
# External storage dir for the emulated Android app's
|
||||
android.files.externalStorageDir = ${ts.server.rootDir}/android-compat/extappdata
|
||||
|
||||
# Internal Android directories
|
||||
android.files.dataDir = ${android.files.rootDir}/data
|
||||
android.files.filesDir = ${android.files.rootDir}/files
|
||||
android.files.cacheDir = ${android.files.rootDir}/cache
|
||||
android.files.codeCacheDir = ${android.files.rootDir}/code_cache
|
||||
android.files.noBackupFilesDir = ${android.files.rootDir}/no_backup
|
||||
android.files.databasesDir = ${android.files.rootDir}/databases
|
||||
android.files.prefsDir = ${android.files.rootDir}/shared_prefs
|
||||
|
||||
# External Android directories
|
||||
android.files.externalFilesDirs = [${android.files.externalStorageDir}/files]
|
||||
android.files.obbDirs = [${android.files.externalStorageDir}/obb]
|
||||
android.files.externalCacheDirs = [${android.files.externalStorageDir}/cache]
|
||||
android.files.externalMediaDirs = [${android.files.externalStorageDir}/media]
|
||||
android.files.downloadCacheDir = ${android.files.externalStorageDir}/downloadCache
|
||||
|
||||
android.files.packageDir = ${ts.server.rootDir}/android-compat/packages
|
||||
|
||||
# Emulated Android app package name
|
||||
android.app.packageName = eu.kanade.tachiyomi
|
||||
# Debug mode for the emulated Android app
|
||||
android.app.debug = true
|
||||
|
||||
# Whether or not the emulated Android system is debuggable
|
||||
android.system.isDebuggable = true
|
||||
|
||||
# Is the multi-user sync server enabled? Does not affect the single-user sync server included in the API.
|
||||
ts.syncd.enable = false
|
||||
|
||||
# The URL of this server (displayed in the sync server web ui)
|
||||
ts.syncd.baseUrl = "http://example.com"
|
||||
|
||||
# 'true' to disable the API and only enable the multi-user sync server
|
||||
ts.syncd.syncOnlyMode = false
|
||||
|
||||
# The root directory to store synchronized data
|
||||
ts.syncd.rootDir = ${ts.server.rootDir}/sync/accounts
|
||||
|
||||
# Location to store config files for the sandbox
|
||||
ts.syncd.sandboxedConfig = ${ts.server.rootDir}/sync/sandboxed_config.config
|
||||
|
||||
# Recaptcha stuff for signup/login
|
||||
ts.syncd.recaptcha.siteKey = ""
|
||||
ts.syncd.recaptcha.secret = ""
|
||||
|
||||
# Sync server display name
|
||||
ts.syncd.name = "Tachiyomi sync server"
|
||||
|
||||
# Header used to forward the IP to the multi-user sync server if the server is behind a reverse proxy
|
||||
ts.syncd.ipHeader = ""
|
72
AndroidCompat/build.gradle.kts
Normal file
72
AndroidCompat/build.gradle.kts
Normal file
@ -0,0 +1,72 @@
|
||||
|
||||
plugins {
|
||||
application
|
||||
}
|
||||
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
maven {
|
||||
url = uri("https://jitpack.io")
|
||||
}
|
||||
|
||||
maven {
|
||||
url = uri("https://maven.google.com")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Android stub library
|
||||
// compileOnly( fileTree(File(rootProject.rootDir, "libs/android"), include: "*.jar")
|
||||
implementation(fileTree("lib/"))
|
||||
implementation(fileTree("${rootProject.rootDir}/server/lib/dex2jar/"))
|
||||
|
||||
|
||||
// Android JAR libs
|
||||
// compileOnly( fileTree(dir: new File(rootProject.rootDir, "libs/other"), include: "*.jar")
|
||||
|
||||
// JSON
|
||||
compileOnly( "com.google.code.gson:gson:2.8.6")
|
||||
|
||||
// Javassist
|
||||
compileOnly( "org.javassist:javassist:3.27.0-GA")
|
||||
|
||||
// Coroutines
|
||||
val kotlinx_coroutines_version = "1.4.2"
|
||||
compileOnly( "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinx_coroutines_version")
|
||||
compileOnly( "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$kotlinx_coroutines_version")
|
||||
|
||||
// XML
|
||||
compileOnly( group= "xmlpull", name= "xmlpull", version= "1.1.3.1")
|
||||
|
||||
// Config API
|
||||
implementation( project(":AndroidCompat:Config"))
|
||||
|
||||
// dex2jar
|
||||
// compileOnly( "dex2jar:dex-translator")
|
||||
|
||||
// APK parser
|
||||
compileOnly("net.dongliu:apk-parser:2.6.10")
|
||||
|
||||
// APK sig verifier
|
||||
compileOnly("com.android.tools.build:apksig:4.2.0-alpha13")
|
||||
|
||||
// AndroidX annotations
|
||||
compileOnly( "androidx.annotation:annotation:1.2.0-alpha01")
|
||||
|
||||
// compileOnly("io.reactivex:rxjava:1.3.8")
|
||||
}
|
||||
|
||||
//def fatJarTask = tasks.getByPath(':AndroidCompat:JVMPatch:fatJar')
|
||||
//
|
||||
//// Copy JVM core patches
|
||||
//task copyJVMPatches(type: Copy) {
|
||||
// from fatJarTask.outputs.files
|
||||
// into 'src/main/resources/patches'
|
||||
//}
|
||||
//
|
||||
//compileOnly(Java.dependsOn gradle.includedBuild('dex2jar').task(':dex-translator:assemble')
|
||||
//compileOnly(Java.dependsOn copyJVMPatches
|
||||
//copyJVMPatches.dependsOn fatJarTask
|
||||
//
|
1
AndroidCompat/lib/.gitignore
vendored
Normal file
1
AndroidCompat/lib/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
android.jar
|
35
AndroidCompat/src/main/java/android/annotation/AnimRes.java
Normal file
35
AndroidCompat/src/main/java/android/annotation/AnimRes.java
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be an anim resource reference (e.g. {@link android.R.anim#fade_in}).
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface AnimRes {
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be an animator resource reference (e.g. {@link android.R.animator#fade_in}).
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface AnimatorRes {
|
||||
}
|
37
AndroidCompat/src/main/java/android/annotation/AnyRes.java
Normal file
37
AndroidCompat/src/main/java/android/annotation/AnyRes.java
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be a resource reference of any type. If the specific type is known, use
|
||||
* one of the more specific annotations instead, such as {@link StringRes} or
|
||||
* {@link DrawableRes}.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface AnyRes {
|
||||
}
|
34
AndroidCompat/src/main/java/android/annotation/AppIdInt.java
Normal file
34
AndroidCompat/src/main/java/android/annotation/AppIdInt.java
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that the annotated element is a multi-user application ID. This is
|
||||
* <em>not</em> the same as a UID.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface AppIdInt {
|
||||
}
|
35
AndroidCompat/src/main/java/android/annotation/ArrayRes.java
Normal file
35
AndroidCompat/src/main/java/android/annotation/ArrayRes.java
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be an array resource reference (e.g. {@link android.R.array#phoneTypes}).
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface ArrayRes {
|
||||
}
|
35
AndroidCompat/src/main/java/android/annotation/AttrRes.java
Normal file
35
AndroidCompat/src/main/java/android/annotation/AttrRes.java
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be an attribute reference (e.g. {@link android.R.attr#action}).
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface AttrRes {
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that the annotated method should only be called on the binder thread.
|
||||
* If the annotated element is a class, then all methods in the class should be called
|
||||
* on the binder thread.
|
||||
* <p>
|
||||
* Example:
|
||||
* <pre><code>
|
||||
* @BinderThread
|
||||
* public BeamShareData createBeamShareData() { ... }
|
||||
* </code></pre>
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD,CONSTRUCTOR,TYPE})
|
||||
public @interface BinderThread {
|
||||
}
|
35
AndroidCompat/src/main/java/android/annotation/BoolRes.java
Normal file
35
AndroidCompat/src/main/java/android/annotation/BoolRes.java
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be a boolean resource reference.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface BoolRes {
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that any overriding methods should invoke this method as well.
|
||||
* <p>
|
||||
* Example:
|
||||
* <pre><code>
|
||||
* @CallSuper
|
||||
* public abstract void onFocusLost();
|
||||
* </code></pre>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD})
|
||||
public @interface CallSuper {
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that the annotated method returns a result that it typically is
|
||||
* an error to ignore. This is usually used for methods that have no side effect,
|
||||
* so calling it without actually looking at the result usually means the developer
|
||||
* has misunderstood what the method does.
|
||||
* <p>
|
||||
* Example:
|
||||
* <pre>{@code
|
||||
* public @CheckResult String trim(String s) { return s.trim(); }
|
||||
* ...
|
||||
* s.trim(); // this is probably an error
|
||||
* s = s.trim(); // ok
|
||||
* }</pre>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD})
|
||||
public @interface CheckResult {
|
||||
/** Defines the name of the suggested method to use instead, if applicable (using
|
||||
* the same signature format as javadoc.) If there is more than one possibility,
|
||||
* list them all separated by commas.
|
||||
* <p>
|
||||
* For example, ProcessBuilder has a method named {@code redirectErrorStream()}
|
||||
* which sounds like it might redirect the error stream. It does not. It's just
|
||||
* a getter which returns whether the process builder will redirect the error stream,
|
||||
* and to actually set it, you must call {@code redirectErrorStream(boolean)}.
|
||||
* In that case, the method should be defined like this:
|
||||
* <pre>
|
||||
* @CheckResult(suggest="#redirectErrorStream(boolean)")
|
||||
* public boolean redirectErrorStream() { ... }
|
||||
* </pre>
|
||||
*/
|
||||
String suggest() default "";
|
||||
}
|
39
AndroidCompat/src/main/java/android/annotation/ColorInt.java
Normal file
39
AndroidCompat/src/main/java/android/annotation/ColorInt.java
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that the annotated element represents a packed color
|
||||
* int, {@code AARRGGBB}. If applied to an int array, every element
|
||||
* in the array represents a color integer.
|
||||
* <p>
|
||||
* Example:
|
||||
* <pre>{@code
|
||||
* public abstract void setTextColor(@ColorInt int color);
|
||||
* }</pre>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@Target({PARAMETER,METHOD,LOCAL_VARIABLE,FIELD})
|
||||
public @interface ColorInt {
|
||||
}
|
35
AndroidCompat/src/main/java/android/annotation/ColorRes.java
Normal file
35
AndroidCompat/src/main/java/android/annotation/ColorRes.java
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be a color resource reference (e.g. {@link android.R.color#black}).
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface ColorRes {
|
||||
}
|
35
AndroidCompat/src/main/java/android/annotation/DimenRes.java
Normal file
35
AndroidCompat/src/main/java/android/annotation/DimenRes.java
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be a dimension resource reference (e.g. {@link android.R.dimen#app_icon_size}).
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface DimenRes {
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be a drawable resource reference (e.g. {@link android.R.attr#alertDialogIcon}).
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface DrawableRes {
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that the annotated element should be a float or double in the given range
|
||||
* <p>
|
||||
* Example:
|
||||
* <pre><code>
|
||||
* @FloatRange(from=0.0,to=1.0)
|
||||
* public float getAlpha() {
|
||||
* ...
|
||||
* }
|
||||
* </code></pre>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD,PARAMETER,FIELD,LOCAL_VARIABLE})
|
||||
public @interface FloatRange {
|
||||
/** Smallest value. Whether it is inclusive or not is determined
|
||||
* by {@link #fromInclusive} */
|
||||
double from() default Double.NEGATIVE_INFINITY;
|
||||
/** Largest value. Whether it is inclusive or not is determined
|
||||
* by {@link #toInclusive} */
|
||||
double to() default Double.POSITIVE_INFINITY;
|
||||
|
||||
/** Whether the from value is included in the range */
|
||||
boolean fromInclusive() default true;
|
||||
|
||||
/** Whether the to value is included in the range */
|
||||
boolean toInclusive() default true;
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be a fraction resource reference.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface FractionRes {
|
||||
}
|
35
AndroidCompat/src/main/java/android/annotation/IdRes.java
Normal file
35
AndroidCompat/src/main/java/android/annotation/IdRes.java
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be an id resource reference (e.g. {@link android.R.id#copy}).
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface IdRes {
|
||||
}
|
57
AndroidCompat/src/main/java/android/annotation/IntDef.java
Normal file
57
AndroidCompat/src/main/java/android/annotation/IntDef.java
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
/**
|
||||
* Denotes that the annotated element of integer type, represents
|
||||
* a logical type and that its value should be one of the explicitly
|
||||
* named constants. If the {@link #flag()} attribute is set to true,
|
||||
* multiple constants can be combined.
|
||||
* <p>
|
||||
* <pre><code>
|
||||
* @Retention(SOURCE)
|
||||
* @IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
|
||||
* public @interface NavigationMode {}
|
||||
* public static final int NAVIGATION_MODE_STANDARD = 0;
|
||||
* public static final int NAVIGATION_MODE_LIST = 1;
|
||||
* public static final int NAVIGATION_MODE_TABS = 2;
|
||||
* ...
|
||||
* public abstract void setNavigationMode(@NavigationMode int mode);
|
||||
* @NavigationMode
|
||||
* public abstract int getNavigationMode();
|
||||
* </code></pre>
|
||||
* For a flag, set the flag attribute:
|
||||
* <pre><code>
|
||||
* @IntDef(
|
||||
* flag = true,
|
||||
* value = {NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
|
||||
* </code></pre>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@Target({ANNOTATION_TYPE})
|
||||
public @interface IntDef {
|
||||
/** Defines the constant prefix for this element */
|
||||
String[] prefix() default "";
|
||||
/** Defines the allowed constants for this element */
|
||||
long[] value() default {};
|
||||
/** Defines whether the constants can be used as a flag, or just as an enum (the default) */
|
||||
boolean flag() default false;
|
||||
}
|
44
AndroidCompat/src/main/java/android/annotation/IntRange.java
Normal file
44
AndroidCompat/src/main/java/android/annotation/IntRange.java
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that the annotated element should be an int or long in the given range
|
||||
* <p>
|
||||
* Example:
|
||||
* <pre><code>
|
||||
* @IntRange(from=0,to=255)
|
||||
* public int getAlpha() {
|
||||
* ...
|
||||
* }
|
||||
* </code></pre>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD,PARAMETER,FIELD,LOCAL_VARIABLE,ANNOTATION_TYPE})
|
||||
public @interface IntRange {
|
||||
/** Smallest value, inclusive */
|
||||
long from() default Long.MIN_VALUE;
|
||||
/** Largest value, inclusive */
|
||||
long to() default Long.MAX_VALUE;
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be an integer resource reference (e.g. {@link android.R.integer#config_shortAnimTime}).
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface IntegerRes {
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be an interpolator resource reference (e.g. {@link android.R.interpolator#cycle}).
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface InterpolatorRes {
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be a layout resource reference (e.g. {@link android.R.layout#list_content}).
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface LayoutRes {
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that the annotated method should only be called on the main thread.
|
||||
* If the annotated element is a class, then all methods in the class should be called
|
||||
* on the main thread.
|
||||
* <p>
|
||||
* Example:
|
||||
* <pre><code>
|
||||
* @MainThread
|
||||
* public void deliverResult(D data) { ... }
|
||||
* </code></pre>
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD,CONSTRUCTOR,TYPE})
|
||||
public @interface MainThread {
|
||||
}
|
35
AndroidCompat/src/main/java/android/annotation/MenuRes.java
Normal file
35
AndroidCompat/src/main/java/android/annotation/MenuRes.java
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be a menu resource reference.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface MenuRes {
|
||||
}
|
34
AndroidCompat/src/main/java/android/annotation/NonNull.java
Normal file
34
AndroidCompat/src/main/java/android/annotation/NonNull.java
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that a parameter, field or method return value can never be null.
|
||||
* <p>
|
||||
* This is a marker annotation and it has no specific attributes.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface NonNull {
|
||||
}
|
41
AndroidCompat/src/main/java/android/annotation/Nullable.java
Normal file
41
AndroidCompat/src/main/java/android/annotation/Nullable.java
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that a parameter, field or method return value can be null.
|
||||
* <p>
|
||||
* When decorating a method call parameter, this denotes that the parameter can
|
||||
* legitimately be null and the method will gracefully deal with it. Typically
|
||||
* used on optional parameters.
|
||||
* <p>
|
||||
* When decorating a method, this denotes the method might legitimately return
|
||||
* null.
|
||||
* <p>
|
||||
* This is a marker annotation and it has no specific attributes.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface Nullable {
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be a plurals resource reference.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface PluralsRes {
|
||||
}
|
35
AndroidCompat/src/main/java/android/annotation/RawRes.java
Normal file
35
AndroidCompat/src/main/java/android/annotation/RawRes.java
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be a raw resource reference.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface RawRes {
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that the annotated element requires (or may require) one or more permissions.
|
||||
* <p/>
|
||||
* Example of requiring a single permission:
|
||||
* <pre>{@code
|
||||
* {@literal @}RequiresPermission(Manifest.permission.SET_WALLPAPER)
|
||||
* public abstract void setWallpaper(Bitmap bitmap) throws IOException;
|
||||
*
|
||||
* {@literal @}RequiresPermission(ACCESS_COARSE_LOCATION)
|
||||
* public abstract Location getLastKnownLocation(String provider);
|
||||
* }</pre>
|
||||
* Example of requiring at least one permission from a set:
|
||||
* <pre>{@code
|
||||
* {@literal @}RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
|
||||
* public abstract Location getLastKnownLocation(String provider);
|
||||
* }</pre>
|
||||
* Example of requiring multiple permissions:
|
||||
* <pre>{@code
|
||||
* {@literal @}RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
|
||||
* public abstract Location getLastKnownLocation(String provider);
|
||||
* }</pre>
|
||||
* Example of requiring separate read and write permissions for a content provider:
|
||||
* <pre>{@code
|
||||
* {@literal @}RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))
|
||||
* {@literal @}RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))
|
||||
* public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");
|
||||
* }</pre>
|
||||
* <p>
|
||||
* When specified on a parameter, the annotation indicates that the method requires
|
||||
* a permission which depends on the value of the parameter. For example, consider
|
||||
* {@link android.app.Activity#startActivity(Intent)}:
|
||||
* <pre>{@code
|
||||
* public void startActivity(@RequiresPermission Intent intent) { ... }
|
||||
* }</pre>
|
||||
* Notice how there are no actual permission names listed in the annotation. The actual
|
||||
* permissions required will depend on the particular intent passed in. For example,
|
||||
* the code may look like this:
|
||||
* <pre>{@code
|
||||
* Intent intent = new Intent(Intent.ACTION_CALL);
|
||||
* startActivity(intent);
|
||||
* }</pre>
|
||||
* and the actual permission requirement for this particular intent is described on
|
||||
* the Intent name itself:
|
||||
* <pre>{@code
|
||||
* {@literal @}RequiresPermission(Manifest.permission.CALL_PHONE)
|
||||
* public static final String ACTION_CALL = "android.intent.action.CALL";
|
||||
* }</pre>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@Target({ANNOTATION_TYPE,METHOD,CONSTRUCTOR,FIELD,PARAMETER})
|
||||
public @interface RequiresPermission {
|
||||
/**
|
||||
* The name of the permission that is required, if precisely one permission
|
||||
* is required. If more than one permission is required, specify either
|
||||
* {@link #allOf()} or {@link #anyOf()} instead.
|
||||
* <p>
|
||||
* If specified, {@link #anyOf()} and {@link #allOf()} must both be null.
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* Specifies a list of permission names that are all required.
|
||||
* <p>
|
||||
* If specified, {@link #anyOf()} and {@link #value()} must both be null.
|
||||
*/
|
||||
String[] allOf() default {};
|
||||
|
||||
/**
|
||||
* Specifies a list of permission names where at least one is required
|
||||
* <p>
|
||||
* If specified, {@link #allOf()} and {@link #value()} must both be null.
|
||||
*/
|
||||
String[] anyOf() default {};
|
||||
|
||||
/**
|
||||
* If true, the permission may not be required in all cases (e.g. it may only be
|
||||
* enforced on certain platforms, or for certain call parameters, etc.
|
||||
*/
|
||||
boolean conditional() default false;
|
||||
|
||||
/**
|
||||
* Specifies that the given permission is required for read operations.
|
||||
* <p>
|
||||
* When specified on a parameter, the annotation indicates that the method requires
|
||||
* a permission which depends on the value of the parameter (and typically
|
||||
* the corresponding field passed in will be one of a set of constants which have
|
||||
* been annotated with a <code>@RequiresPermission</code> annotation.)
|
||||
*/
|
||||
@Target({FIELD, METHOD, PARAMETER})
|
||||
@interface Read {
|
||||
RequiresPermission value() default @RequiresPermission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that the given permission is required for write operations.
|
||||
* <p>
|
||||
* When specified on a parameter, the annotation indicates that the method requires
|
||||
* a permission which depends on the value of the parameter (and typically
|
||||
* the corresponding field passed in will be one of a set of constants which have
|
||||
* been annotated with a <code>@RequiresPermission</code> annotation.)
|
||||
*/
|
||||
@Target({FIELD, METHOD, PARAMETER})
|
||||
@interface Write {
|
||||
RequiresPermission value() default @RequiresPermission;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Indicates a constant field value should be exported to be used in the SDK tools.
|
||||
* @hide
|
||||
*/
|
||||
@Target({ ElementType.FIELD })
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface SdkConstant {
|
||||
public static enum SdkConstantType {
|
||||
ACTIVITY_INTENT_ACTION, BROADCAST_INTENT_ACTION, SERVICE_ACTION, INTENT_CATEGORY, FEATURE;
|
||||
}
|
||||
|
||||
SdkConstantType value();
|
||||
}
|
49
AndroidCompat/src/main/java/android/annotation/Size.java
Normal file
49
AndroidCompat/src/main/java/android/annotation/Size.java
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that the annotated element should have a given size or length.
|
||||
* Note that "-1" means "unset". Typically used with a parameter or
|
||||
* return value of type array or collection.
|
||||
* <p>
|
||||
* Example:
|
||||
* <pre>{@code
|
||||
* public void getLocationInWindow(@Size(2) int[] location) {
|
||||
* ...
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@Target({PARAMETER,LOCAL_VARIABLE,METHOD,FIELD})
|
||||
public @interface Size {
|
||||
/** An exact size (or -1 if not specified) */
|
||||
long value() default -1;
|
||||
/** A minimum size, inclusive */
|
||||
long min() default Long.MIN_VALUE;
|
||||
/** A maximum size, inclusive */
|
||||
long max() default Long.MAX_VALUE;
|
||||
/** The size must be a multiple of this factor */
|
||||
long multiple() default 1;
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.CLASS;
|
||||
|
||||
/**
|
||||
* Denotes that the annotated String element, represents a logical
|
||||
* type and that its value should be one of the explicitly named constants.
|
||||
* <p>
|
||||
* Example:
|
||||
* <pre><code>
|
||||
* @Retention(SOURCE)
|
||||
* @StringDef({
|
||||
* POWER_SERVICE,
|
||||
* WINDOW_SERVICE,
|
||||
* LAYOUT_INFLATER_SERVICE
|
||||
* })
|
||||
* public @interface ServiceName {}
|
||||
* public static final String POWER_SERVICE = "power";
|
||||
* public static final String WINDOW_SERVICE = "window";
|
||||
* public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater";
|
||||
* ...
|
||||
* public abstract Object getSystemService(@ServiceName String name);
|
||||
* </code></pre>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Retention(CLASS)
|
||||
@Target({ANNOTATION_TYPE})
|
||||
public @interface StringDef {
|
||||
/** Defines the allowed constants for this element */
|
||||
String[] value() default {};
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be a String resource reference (e.g. {@link android.R.string#ok}).
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface StringRes {
|
||||
}
|
35
AndroidCompat/src/main/java/android/annotation/StyleRes.java
Normal file
35
AndroidCompat/src/main/java/android/annotation/StyleRes.java
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that a integer parameter, field or method return value is expected
|
||||
* to be a style resource reference (e.g. {@link android.R.style#TextAppearance}).
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface StyleRes {
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that a integer parameter, field or method return value is expected
|
||||
* to be a styleable resource reference (e.g. {@link android.R.styleable#TextView_text}).
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface StyleableRes {
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
|
||||
/** Indicates that Lint should ignore the specified warnings for the annotated element. */
|
||||
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
public @interface SuppressLint {
|
||||
/**
|
||||
* The set of warnings (identified by the lint issue id) that should be
|
||||
* ignored by lint. It is not an error to specify an unrecognized name.
|
||||
*/
|
||||
String[] value();
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
|
||||
/**
|
||||
* Indicates an API is exposed for use by bundled system applications.
|
||||
* <p>
|
||||
* These APIs are not guaranteed to remain consistent release-to-release,
|
||||
* and are not for use by apps linking against the Android SDK.
|
||||
* </p><p>
|
||||
* This annotation should only appear on API that is already marked <pre>@hide</pre>.
|
||||
* </p>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE, PACKAGE})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface SystemApi {
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
|
||||
/** Indicates that Lint should treat this type as targeting a given API level, no matter what the
|
||||
project target is. */
|
||||
@Target({TYPE, METHOD, CONSTRUCTOR})
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
public @interface TargetApi {
|
||||
/**
|
||||
* This sets the target api level for the type..
|
||||
*/
|
||||
int value();
|
||||
}
|
37
AndroidCompat/src/main/java/android/annotation/TestApi.java
Normal file
37
AndroidCompat/src/main/java/android/annotation/TestApi.java
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
|
||||
/**
|
||||
* Indicates an API is exposed for use by CTS.
|
||||
* <p>
|
||||
* These APIs are not guaranteed to remain consistent release-to-release,
|
||||
* and are not for use by apps linking against the Android SDK.
|
||||
* </p>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE, PACKAGE})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface TestApi {
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be a transition resource reference.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface TransitionRes {
|
||||
}
|
40
AndroidCompat/src/main/java/android/annotation/UiThread.java
Normal file
40
AndroidCompat/src/main/java/android/annotation/UiThread.java
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that the annotated method or constructor should only be called on the UI thread.
|
||||
* If the annotated element is a class, then all methods in the class should be called
|
||||
* on the UI thread.
|
||||
* <p>
|
||||
* Example:
|
||||
* <pre><code>
|
||||
* @UiThread
|
||||
* public abstract void setText(@NonNull String text) { ... }
|
||||
* </code></pre>
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD,CONSTRUCTOR,TYPE})
|
||||
public @interface UiThread {
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that the annotated element is a multi-user user ID. This is
|
||||
* <em>not</em> the same as a UID.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface UserIdInt {
|
||||
}
|
37
AndroidCompat/src/main/java/android/annotation/Widget.java
Normal file
37
AndroidCompat/src/main/java/android/annotation/Widget.java
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Indicates a class is a widget usable by application developers to create UI.
|
||||
* <p>
|
||||
* This must be used in cases where:
|
||||
* <ul>
|
||||
* <li>The widget is not in the package <code>android.widget</code></li>
|
||||
* <li>The widget extends <code>android.view.ViewGroup</code></li>
|
||||
* </ul>
|
||||
* @hide
|
||||
*/
|
||||
@Target({ ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Widget {
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that the annotated method should only be called on a worker thread.
|
||||
* If the annotated element is a class, then all methods in the class should be called
|
||||
* on a worker thread.
|
||||
* <p>
|
||||
* Example:
|
||||
* <pre><code>
|
||||
* @WorkerThread
|
||||
* protected abstract FilterResults performFiltering(CharSequence constraint);
|
||||
* </code></pre>
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD,CONSTRUCTOR,TYPE})
|
||||
public @interface WorkerThread {
|
||||
}
|
35
AndroidCompat/src/main/java/android/annotation/XmlRes.java
Normal file
35
AndroidCompat/src/main/java/android/annotation/XmlRes.java
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
/**
|
||||
* Denotes that an integer parameter, field or method return value is expected
|
||||
* to be an XML resource reference.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target({METHOD, PARAMETER, FIELD})
|
||||
public @interface XmlRes {
|
||||
}
|
284
AndroidCompat/src/main/java/android/app/Application.java
Normal file
284
AndroidCompat/src/main/java/android/app/Application.java
Normal file
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.app;
|
||||
|
||||
import android.annotation.CallSuper;
|
||||
import android.content.*;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Base class for maintaining global application state. You can provide your own
|
||||
* implementation by creating a subclass and specifying the fully-qualified name
|
||||
* of this subclass as the <code>"android:name"</code> attribute in your
|
||||
* AndroidManifest.xml's <code><application></code> tag. The Application
|
||||
* class, or your subclass of the Application class, is instantiated before any
|
||||
* other class when the process for your application/package is created.
|
||||
*
|
||||
* <p class="note"><strong>Note: </strong>There is normally no need to subclass
|
||||
* Application. In most situations, static singletons can provide the same
|
||||
* functionality in a more modular way. If your singleton needs a global
|
||||
* context (for example to register broadcast receivers), include
|
||||
* {@link android.content.Context#getApplicationContext() Context.getApplicationContext()}
|
||||
* as a {@link android.content.Context} argument when invoking your singleton's
|
||||
* <code>getInstance()</code> method.
|
||||
* </p>
|
||||
*/
|
||||
public class Application extends ContextWrapper implements ComponentCallbacks2 {
|
||||
private ArrayList<ComponentCallbacks> mComponentCallbacks =
|
||||
new ArrayList<ComponentCallbacks>();
|
||||
private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
|
||||
new ArrayList<ActivityLifecycleCallbacks>();
|
||||
private ArrayList<OnProvideAssistDataListener> mAssistCallbacks = null;
|
||||
|
||||
public interface ActivityLifecycleCallbacks {
|
||||
void onActivityCreated(Activity activity, Bundle savedInstanceState);
|
||||
void onActivityStarted(Activity activity);
|
||||
void onActivityResumed(Activity activity);
|
||||
void onActivityPaused(Activity activity);
|
||||
void onActivityStopped(Activity activity);
|
||||
void onActivitySaveInstanceState(Activity activity, Bundle outState);
|
||||
void onActivityDestroyed(Activity activity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback interface for use with {@link Application#registerOnProvideAssistDataListener}
|
||||
* and {@link Application#unregisterOnProvideAssistDataListener}.
|
||||
*/
|
||||
public interface OnProvideAssistDataListener {
|
||||
/**
|
||||
* This is called when the user is requesting an assist, to build a full
|
||||
* {@link Intent#ACTION_ASSIST} Intent with all of the context of the current
|
||||
* application. You can override this method to place into the bundle anything
|
||||
* you would like to appear in the {@link Intent#EXTRA_ASSIST_CONTEXT} part
|
||||
* of the assist Intent.
|
||||
*/
|
||||
public void onProvideAssistData(Activity activity, Bundle data);
|
||||
}
|
||||
|
||||
public Application() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the application is starting, before any activity, service,
|
||||
* or receiver objects (excluding content providers) have been created.
|
||||
* Implementations should be as quick as possible (for example using
|
||||
* lazy initialization of state) since the time spent in this function
|
||||
* directly impacts the performance of starting the first activity,
|
||||
* service, or receiver in a process.
|
||||
* If you override this method, be sure to call super.onCreate().
|
||||
*/
|
||||
@CallSuper
|
||||
public void onCreate() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is for use in emulated process environments. It will
|
||||
* never be called on a production Android device, where processes are
|
||||
* removed by simply killing them; no user code (including this callback)
|
||||
* is executed when doing so.
|
||||
*/
|
||||
@CallSuper
|
||||
public void onTerminate() {
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
Object[] callbacks = collectComponentCallbacks();
|
||||
if (callbacks != null) {
|
||||
for (int i=0; i<callbacks.length; i++) {
|
||||
((ComponentCallbacks)callbacks[i]).onConfigurationChanged(newConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
public void onLowMemory() {
|
||||
Object[] callbacks = collectComponentCallbacks();
|
||||
if (callbacks != null) {
|
||||
for (int i=0; i<callbacks.length; i++) {
|
||||
((ComponentCallbacks)callbacks[i]).onLowMemory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
public void onTrimMemory(int level) {
|
||||
Object[] callbacks = collectComponentCallbacks();
|
||||
if (callbacks != null) {
|
||||
for (int i=0; i<callbacks.length; i++) {
|
||||
Object c = callbacks[i];
|
||||
if (c instanceof ComponentCallbacks2) {
|
||||
((ComponentCallbacks2)c).onTrimMemory(level);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void registerComponentCallbacks(ComponentCallbacks callback) {
|
||||
synchronized (mComponentCallbacks) {
|
||||
mComponentCallbacks.add(callback);
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterComponentCallbacks(ComponentCallbacks callback) {
|
||||
synchronized (mComponentCallbacks) {
|
||||
mComponentCallbacks.remove(callback);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
|
||||
synchronized (mActivityLifecycleCallbacks) {
|
||||
mActivityLifecycleCallbacks.add(callback);
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
|
||||
synchronized (mActivityLifecycleCallbacks) {
|
||||
mActivityLifecycleCallbacks.remove(callback);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerOnProvideAssistDataListener(OnProvideAssistDataListener callback) {
|
||||
synchronized (this) {
|
||||
if (mAssistCallbacks == null) {
|
||||
mAssistCallbacks = new ArrayList<OnProvideAssistDataListener>();
|
||||
}
|
||||
mAssistCallbacks.add(callback);
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterOnProvideAssistDataListener(OnProvideAssistDataListener callback) {
|
||||
synchronized (this) {
|
||||
if (mAssistCallbacks != null) {
|
||||
mAssistCallbacks.remove(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ Internal API ------------------
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final void attach(Context context) {
|
||||
attachBaseContext(context);
|
||||
}
|
||||
|
||||
/* package */ void dispatchActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||
Object[] callbacks = collectActivityLifecycleCallbacks();
|
||||
if (callbacks != null) {
|
||||
for (int i=0; i<callbacks.length; i++) {
|
||||
((ActivityLifecycleCallbacks)callbacks[i]).onActivityCreated(activity,
|
||||
savedInstanceState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ void dispatchActivityStarted(Activity activity) {
|
||||
Object[] callbacks = collectActivityLifecycleCallbacks();
|
||||
if (callbacks != null) {
|
||||
for (int i=0; i<callbacks.length; i++) {
|
||||
((ActivityLifecycleCallbacks)callbacks[i]).onActivityStarted(activity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ void dispatchActivityResumed(Activity activity) {
|
||||
Object[] callbacks = collectActivityLifecycleCallbacks();
|
||||
if (callbacks != null) {
|
||||
for (int i=0; i<callbacks.length; i++) {
|
||||
((ActivityLifecycleCallbacks)callbacks[i]).onActivityResumed(activity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ void dispatchActivityPaused(Activity activity) {
|
||||
Object[] callbacks = collectActivityLifecycleCallbacks();
|
||||
if (callbacks != null) {
|
||||
for (int i=0; i<callbacks.length; i++) {
|
||||
((ActivityLifecycleCallbacks)callbacks[i]).onActivityPaused(activity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ void dispatchActivityStopped(Activity activity) {
|
||||
Object[] callbacks = collectActivityLifecycleCallbacks();
|
||||
if (callbacks != null) {
|
||||
for (int i=0; i<callbacks.length; i++) {
|
||||
((ActivityLifecycleCallbacks)callbacks[i]).onActivityStopped(activity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ void dispatchActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||
Object[] callbacks = collectActivityLifecycleCallbacks();
|
||||
if (callbacks != null) {
|
||||
for (int i=0; i<callbacks.length; i++) {
|
||||
((ActivityLifecycleCallbacks)callbacks[i]).onActivitySaveInstanceState(activity,
|
||||
outState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ void dispatchActivityDestroyed(Activity activity) {
|
||||
Object[] callbacks = collectActivityLifecycleCallbacks();
|
||||
if (callbacks != null) {
|
||||
for (int i=0; i<callbacks.length; i++) {
|
||||
((ActivityLifecycleCallbacks)callbacks[i]).onActivityDestroyed(activity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object[] collectComponentCallbacks() {
|
||||
Object[] callbacks = null;
|
||||
synchronized (mComponentCallbacks) {
|
||||
if (mComponentCallbacks.size() > 0) {
|
||||
callbacks = mComponentCallbacks.toArray();
|
||||
}
|
||||
}
|
||||
return callbacks;
|
||||
}
|
||||
|
||||
private Object[] collectActivityLifecycleCallbacks() {
|
||||
Object[] callbacks = null;
|
||||
synchronized (mActivityLifecycleCallbacks) {
|
||||
if (mActivityLifecycleCallbacks.size() > 0) {
|
||||
callbacks = mActivityLifecycleCallbacks.toArray();
|
||||
}
|
||||
}
|
||||
return callbacks;
|
||||
}
|
||||
|
||||
/* package */ void dispatchOnProvideAssistData(Activity activity, Bundle data) {
|
||||
Object[] callbacks;
|
||||
synchronized (this) {
|
||||
if (mAssistCallbacks == null) {
|
||||
return;
|
||||
}
|
||||
callbacks = mAssistCallbacks.toArray();
|
||||
}
|
||||
if (callbacks != null) {
|
||||
for (int i=0; i<callbacks.length; i++) {
|
||||
((OnProvideAssistDataListener)callbacks[i]).onProvideAssistData(activity, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.app;
|
||||
import android.content.Intent;
|
||||
/** {@hide} */
|
||||
public class PackageDeleteObserver {
|
||||
public void onUserActionRequired(Intent intent) {
|
||||
}
|
||||
public void onPackageDeleted(String basePackageName, int returnCode, String msg) {
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.app;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
/** {@hide} */
|
||||
public class PackageInstallObserver {
|
||||
public void onUserActionRequired(Intent intent) {
|
||||
}
|
||||
/**
|
||||
* This method will be called to report the result of the package
|
||||
* installation attempt.
|
||||
*
|
||||
* @param basePackageName Name of the package whose installation was
|
||||
* attempted
|
||||
* @param extras If non-null, this Bundle contains extras providing
|
||||
* additional information about an install failure. See
|
||||
* {@link android.content.pm.PackageManager} for documentation
|
||||
* about which extras apply to various failures; in particular
|
||||
* the strings named EXTRA_FAILURE_*.
|
||||
* @param returnCode The numeric success or failure code indicating the
|
||||
* basic outcome
|
||||
* @hide
|
||||
*/
|
||||
public void onPackageInstalled(String basePackageName, int returnCode, String msg,
|
||||
Bundle extras) {
|
||||
}
|
||||
}
|
722
AndroidCompat/src/main/java/android/app/Service.java
Normal file
722
AndroidCompat/src/main/java/android/app/Service.java
Normal file
@ -0,0 +1,722 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.app;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ComponentCallbacks2;
|
||||
import android.content.Intent;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
import kotlin.NotImplementedError;
|
||||
import xyz.nulldev.androidcompat.service.ServiceSupport;
|
||||
import xyz.nulldev.androidcompat.util.KodeinGlobalHelper;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
/**
|
||||
* A Service is an application component representing either an application's desire
|
||||
* to perform a longer-running operation while not interacting with the user
|
||||
* or to supply functionality for other applications to use. Each service
|
||||
* class must have a corresponding
|
||||
* {@link android.R.styleable#AndroidManifestService <service>}
|
||||
* declaration in its package's <code>AndroidManifest.xml</code>. Services
|
||||
* can be started with
|
||||
* {@link android.content.Context#startService Context.startService()} and
|
||||
* {@link android.content.Context#bindService Context.bindService()}.
|
||||
*
|
||||
* <p>Note that services, like other application objects, run in the main
|
||||
* thread of their hosting process. This means that, if your service is going
|
||||
* to do any CPU intensive (such as MP3 playback) or blocking (such as
|
||||
* networking) operations, it should spawn its own thread in which to do that
|
||||
* work. More information on this can be found in
|
||||
* <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html">Processes and
|
||||
* Threads</a>. The {@link IntentService} class is available
|
||||
* as a standard implementation of Service that has its own thread where it
|
||||
* schedules its work to be done.</p>
|
||||
*
|
||||
* <p>Topics covered here:
|
||||
* <ol>
|
||||
* <li><a href="#WhatIsAService">What is a Service?</a>
|
||||
* <li><a href="#ServiceLifecycle">Service Lifecycle</a>
|
||||
* <li><a href="#Permissions">Permissions</a>
|
||||
* <li><a href="#ProcessLifecycle">Process Lifecycle</a>
|
||||
* <li><a href="#LocalServiceSample">Local Service Sample</a>
|
||||
* <li><a href="#RemoteMessengerServiceSample">Remote Messenger Service Sample</a>
|
||||
* </ol>
|
||||
*
|
||||
* <div class="special reference">
|
||||
* <h3>Developer Guides</h3>
|
||||
* <p>For a detailed discussion about how to create services, read the
|
||||
* <a href="{@docRoot}guide/topics/fundamentals/services.html">Services</a> developer guide.</p>
|
||||
* </div>
|
||||
*
|
||||
* <a name="WhatIsAService"></a>
|
||||
* <h3>What is a Service?</h3>
|
||||
*
|
||||
* <p>Most confusion about the Service class actually revolves around what
|
||||
* it is <em>not</em>:</p>
|
||||
*
|
||||
* <ul>
|
||||
* <li> A Service is <b>not</b> a separate process. The Service object itself
|
||||
* does not imply it is running in its own process; unless otherwise specified,
|
||||
* it runs in the same process as the application it is part of.
|
||||
* <li> A Service is <b>not</b> a thread. It is not a means itself to do work off
|
||||
* of the main thread (to avoid Application Not Responding errors).
|
||||
* </ul>
|
||||
*
|
||||
* <p>Thus a Service itself is actually very simple, providing two main features:</p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>A facility for the application to tell the system <em>about</em>
|
||||
* something it wants to be doing in the background (even when the user is not
|
||||
* directly interacting with the application). This corresponds to calls to
|
||||
* {@link android.content.Context#startService Context.startService()}, which
|
||||
* ask the system to schedule work for the service, to be run until the service
|
||||
* or someone else explicitly stop it.
|
||||
* <li>A facility for an application to expose some of its functionality to
|
||||
* other applications. This corresponds to calls to
|
||||
* {@link android.content.Context#bindService Context.bindService()}, which
|
||||
* allows a long-standing connection to be made to the service in order to
|
||||
* interact with it.
|
||||
* </ul>
|
||||
*
|
||||
* <p>When a Service component is actually created, for either of these reasons,
|
||||
* all that the system actually does is instantiate the component
|
||||
* and call its {@link #onCreate} and any other appropriate callbacks on the
|
||||
* main thread. It is up to the Service to implement these with the appropriate
|
||||
* behavior, such as creating a secondary thread in which it does its work.</p>
|
||||
*
|
||||
* <p>Note that because Service itself is so simple, you can make your
|
||||
* interaction with it as simple or complicated as you want: from treating it
|
||||
* as a local Java object that you make direct method calls on (as illustrated
|
||||
* by <a href="#LocalServiceSample">Local Service Sample</a>), to providing
|
||||
* a full remoteable interface using AIDL.</p>
|
||||
*
|
||||
* <a name="ServiceLifecycle"></a>
|
||||
* <h3>Service Lifecycle</h3>
|
||||
*
|
||||
* <p>There are two reasons that a service can be run by the system. If someone
|
||||
* calls {@link android.content.Context#startService Context.startService()} then the system will
|
||||
* retrieve the service (creating it and calling its {@link #onCreate} method
|
||||
* if needed) and then call its {@link #onStartCommand} method with the
|
||||
* arguments supplied by the client. The service will at this point continue
|
||||
* running until {@link android.content.Context#stopService Context.stopService()} or
|
||||
* {@link #stopSelf()} is called. Note that multiple calls to
|
||||
* Context.startService() do not nest (though they do result in multiple corresponding
|
||||
* calls to onStartCommand()), so no matter how many times it is started a service
|
||||
* will be stopped once Context.stopService() or stopSelf() is called; however,
|
||||
* services can use their {@link #stopSelf(int)} method to ensure the service is
|
||||
* not stopped until started intents have been processed.
|
||||
*
|
||||
* <p>For started services, there are two additional major modes of operation
|
||||
* they can decide to run in, depending on the value they return from
|
||||
* onStartCommand(): {@link #START_STICKY} is used for services that are
|
||||
* explicitly started and stopped as needed, while {@link #START_NOT_STICKY}
|
||||
* or {@link #START_REDELIVER_INTENT} are used for services that should only
|
||||
* remain running while processing any commands sent to them. See the linked
|
||||
* documentation for more detail on the semantics.
|
||||
*
|
||||
* <p>Clients can also use {@link android.content.Context#bindService Context.bindService()} to
|
||||
* obtain a persistent connection to a service. This likewise creates the
|
||||
* service if it is not already running (calling {@link #onCreate} while
|
||||
* doing so), but does not call onStartCommand(). The client will receive the
|
||||
* {@link android.os.IBinder} object that the service returns from its
|
||||
* {@link #onBind} method, allowing the client to then make calls back
|
||||
* to the service. The service will remain running as long as the connection
|
||||
* is established (whether or not the client retains a reference on the
|
||||
* service's IBinder). Usually the IBinder returned is for a complex
|
||||
* interface that has been <a href="{@docRoot}guide/components/aidl.html">written
|
||||
* in aidl</a>.
|
||||
*
|
||||
* <p>A service can be both started and have connections bound to it. In such
|
||||
* a case, the system will keep the service running as long as either it is
|
||||
* started <em>or</em> there are one or more connections to it with the
|
||||
* {@link android.content.Context#BIND_AUTO_CREATE Context.BIND_AUTO_CREATE}
|
||||
* flag. Once neither
|
||||
* of these situations hold, the service's {@link #onDestroy} method is called
|
||||
* and the service is effectively terminated. All cleanup (stopping threads,
|
||||
* unregistering receivers) should be complete upon returning from onDestroy().
|
||||
*
|
||||
* <a name="Permissions"></a>
|
||||
* <h3>Permissions</h3>
|
||||
*
|
||||
* <p>Global access to a service can be enforced when it is declared in its
|
||||
* manifest's {@link android.R.styleable#AndroidManifestService <service>}
|
||||
* tag. By doing so, other applications will need to declare a corresponding
|
||||
* {@link android.R.styleable#AndroidManifestUsesPermission <uses-permission>}
|
||||
* element in their own manifest to be able to start, stop, or bind to
|
||||
* the service.
|
||||
*
|
||||
* <p>As of {@link android.os.Build.VERSION_CODES#GINGERBREAD}, when using
|
||||
* {@link Context#startService(Intent) Context.startService(Intent)}, you can
|
||||
* also set {@link Intent#FLAG_GRANT_READ_URI_PERMISSION
|
||||
* Intent.FLAG_GRANT_READ_URI_PERMISSION} and/or {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
* Intent.FLAG_GRANT_WRITE_URI_PERMISSION} on the Intent. This will grant the
|
||||
* Service temporary access to the specific URIs in the Intent. Access will
|
||||
* remain until the Service has called {@link #stopSelf(int)} for that start
|
||||
* command or a later one, or until the Service has been completely stopped.
|
||||
* This works for granting access to the other apps that have not requested
|
||||
* the permission protecting the Service, or even when the Service is not
|
||||
* exported at all.
|
||||
*
|
||||
* <p>In addition, a service can protect individual IPC calls into it with
|
||||
* permissions, by calling the
|
||||
* {@link #checkCallingPermission}
|
||||
* method before executing the implementation of that call.
|
||||
*
|
||||
* <p>See the <a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a>
|
||||
* document for more information on permissions and security in general.
|
||||
*
|
||||
* <a name="ProcessLifecycle"></a>
|
||||
* <h3>Process Lifecycle</h3>
|
||||
*
|
||||
* <p>The Android system will attempt to keep the process hosting a service
|
||||
* around as long as the service has been started or has clients bound to it.
|
||||
* When running low on memory and needing to kill existing processes, the
|
||||
* priority of a process hosting the service will be the higher of the
|
||||
* following possibilities:
|
||||
*
|
||||
* <ul>
|
||||
* <li><p>If the service is currently executing code in its
|
||||
* {@link #onCreate onCreate()}, {@link #onStartCommand onStartCommand()},
|
||||
* or {@link #onDestroy onDestroy()} methods, then the hosting process will
|
||||
* be a foreground process to ensure this code can execute without
|
||||
* being killed.
|
||||
* <li><p>If the service has been started, then its hosting process is considered
|
||||
* to be less important than any processes that are currently visible to the
|
||||
* user on-screen, but more important than any process not visible. Because
|
||||
* only a few processes are generally visible to the user, this means that
|
||||
* the service should not be killed except in low memory conditions. However, since
|
||||
* the user is not directly aware of a background service, in that state it <em>is</em>
|
||||
* considered a valid candidate to kill, and you should be prepared for this to
|
||||
* happen. In particular, long-running services will be increasingly likely to
|
||||
* kill and are guaranteed to be killed (and restarted if appropriate) if they
|
||||
* remain started long enough.
|
||||
* <li><p>If there are clients bound to the service, then the service's hosting
|
||||
* process is never less important than the most important client. That is,
|
||||
* if one of its clients is visible to the user, then the service itself is
|
||||
* considered to be visible. The way a client's importance impacts the service's
|
||||
* importance can be adjusted through {@link Context#BIND_ABOVE_CLIENT},
|
||||
* {@link Context#BIND_ALLOW_OOM_MANAGEMENT}, {@link Context#BIND_WAIVE_PRIORITY},
|
||||
* {@link Context#BIND_IMPORTANT}, and {@link Context#BIND_ADJUST_WITH_ACTIVITY}.
|
||||
* <li><p>A started service can use the {@link #startForeground(int, Notification)}
|
||||
* API to put the service in a foreground state, where the system considers
|
||||
* it to be something the user is actively aware of and thus not a candidate
|
||||
* for killing when low on memory. (It is still theoretically possible for
|
||||
* the service to be killed under extreme memory pressure from the current
|
||||
* foreground application, but in practice this should not be a concern.)
|
||||
* </ul>
|
||||
*
|
||||
* <p>Note this means that most of the time your service is running, it may
|
||||
* be killed by the system if it is under heavy memory pressure. If this
|
||||
* happens, the system will later try to restart the service. An important
|
||||
* consequence of this is that if you implement {@link #onStartCommand onStartCommand()}
|
||||
* to schedule work to be done asynchronously or in another thread, then you
|
||||
* may want to use {@link #START_FLAG_REDELIVERY} to have the system
|
||||
* re-deliver an Intent for you so that it does not get lost if your service
|
||||
* is killed while processing it.
|
||||
*
|
||||
* <p>Other application components running in the same process as the service
|
||||
* (such as an {@link android.app.Activity}) can, of course, increase the
|
||||
* importance of the overall
|
||||
* process beyond just the importance of the service itself.
|
||||
*
|
||||
* <a name="LocalServiceSample"></a>
|
||||
* <h3>Local Service Sample</h3>
|
||||
*
|
||||
* <p>One of the most common uses of a Service is as a secondary component
|
||||
* running alongside other parts of an application, in the same process as
|
||||
* the rest of the components. All components of an .apk run in the same
|
||||
* process unless explicitly stated otherwise, so this is a typical situation.
|
||||
*
|
||||
* <p>When used in this way, by assuming the
|
||||
* components are in the same process, you can greatly simplify the interaction
|
||||
* between them: clients of the service can simply cast the IBinder they
|
||||
* receive from it to a concrete class published by the service.
|
||||
*
|
||||
* <p>An example of this use of a Service is shown here. First is the Service
|
||||
* itself, publishing a custom class when bound:
|
||||
*
|
||||
* {@sample development/samples/ApiDemos/src/com/example/android/apis/app/LocalService.java
|
||||
* service}
|
||||
*
|
||||
* <p>With that done, one can now write client code that directly accesses the
|
||||
* running service, such as:
|
||||
*
|
||||
* {@sample development/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.java
|
||||
* bind}
|
||||
*
|
||||
* <a name="RemoteMessengerServiceSample"></a>
|
||||
* <h3>Remote Messenger Service Sample</h3>
|
||||
*
|
||||
* <p>If you need to be able to write a Service that can perform complicated
|
||||
* communication with clients in remote processes (beyond simply the use of
|
||||
* {@link Context#startService(Intent) Context.startService} to send
|
||||
* commands to it), then you can use the {@link android.os.Messenger} class
|
||||
* instead of writing full AIDL files.
|
||||
*
|
||||
* <p>An example of a Service that uses Messenger as its client interface
|
||||
* is shown here. First is the Service itself, publishing a Messenger to
|
||||
* an internal Handler when bound:
|
||||
*
|
||||
* {@sample development/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.java
|
||||
* service}
|
||||
*
|
||||
* <p>If we want to make this service run in a remote process (instead of the
|
||||
* standard one for its .apk), we can use <code>android:process</code> in its
|
||||
* manifest tag to specify one:
|
||||
*
|
||||
* {@sample development/samples/ApiDemos/AndroidManifest.xml remote_service_declaration}
|
||||
*
|
||||
* <p>Note that the name "remote" chosen here is arbitrary, and you can use
|
||||
* other names if you want additional processes. The ':' prefix appends the
|
||||
* name to your package's standard process name.
|
||||
*
|
||||
* <p>With that done, clients can now bind to the service and send messages
|
||||
* to it. Note that this allows clients to register with it to receive
|
||||
* messages back as well:
|
||||
*
|
||||
* {@sample development/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.java
|
||||
* bind}
|
||||
*/
|
||||
public abstract class Service extends ContextWrapper implements ComponentCallbacks2 {
|
||||
|
||||
private static final ServiceSupport serviceSupport = KodeinGlobalHelper.instance(ServiceSupport.class);
|
||||
|
||||
private static final String TAG = "Service";
|
||||
/**
|
||||
* Flag for {@link #stopForeground(int)}: if set, the notification previously provided
|
||||
* to {@link #startForeground} will be removed. Otherwise it will remain
|
||||
* until a later call (to {@link #startForeground(int, Notification)} or
|
||||
* {@link #stopForeground(int)} removes it, or the service is destroyed.
|
||||
*/
|
||||
public static final int STOP_FOREGROUND_REMOVE = 1<<0;
|
||||
/**
|
||||
* Flag for {@link #stopForeground(int)}: if set, the notification previously provided
|
||||
* to {@link #startForeground} will be detached from the service. Only makes sense
|
||||
* when {@link #STOP_FOREGROUND_REMOVE} is <b>not</b> set -- in this case, the notification
|
||||
* will remain shown, but be completely detached from the service and so no longer changed
|
||||
* except through direct calls to the notification manager.
|
||||
*/
|
||||
public static final int STOP_FOREGROUND_DETACH = 1<<1;
|
||||
/** @hide */
|
||||
@IntDef(flag = true,
|
||||
value = {
|
||||
STOP_FOREGROUND_REMOVE,
|
||||
STOP_FOREGROUND_DETACH
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface StopForegroundFlags {}
|
||||
public Service() {
|
||||
//==================[THIS LINE MODIFIED FROM ANDROID SOURCE!]==================
|
||||
//Service must be initialized with a base context!
|
||||
super(KodeinGlobalHelper.instance(Context.class));
|
||||
}
|
||||
/** Return the application that owns this service. */
|
||||
public final Application getApplication() {
|
||||
return mApplication;
|
||||
}
|
||||
/**
|
||||
* Called by the system when the service is first created. Do not call this method directly.
|
||||
*/
|
||||
public void onCreate() {
|
||||
}
|
||||
/**
|
||||
* @deprecated Implement {@link #onStartCommand(Intent, int, int)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public void onStart(Intent intent, int startId) {
|
||||
}
|
||||
/**
|
||||
* Bits returned by {@link #onStartCommand} describing how to continue
|
||||
* the service if it is killed. May be {@link #START_STICKY},
|
||||
* {@link #START_NOT_STICKY}, {@link #START_REDELIVER_INTENT},
|
||||
* or {@link #START_STICKY_COMPATIBILITY}.
|
||||
*/
|
||||
public static final int START_CONTINUATION_MASK = 0xf;
|
||||
|
||||
/**
|
||||
* Constant to return from {@link #onStartCommand}: compatibility
|
||||
* version of {@link #START_STICKY} that does not guarantee that
|
||||
* {@link #onStartCommand} will be called again after being killed.
|
||||
*/
|
||||
public static final int START_STICKY_COMPATIBILITY = 0;
|
||||
|
||||
/**
|
||||
* Constant to return from {@link #onStartCommand}: if this service's
|
||||
* process is killed while it is started (after returning from
|
||||
* {@link #onStartCommand}), then leave it in the started state but
|
||||
* don't retain this delivered intent. Later the system will try to
|
||||
* re-create the service. Because it is in the started state, it will
|
||||
* guarantee to call {@link #onStartCommand} after creating the new
|
||||
* service instance; if there are not any pending start commands to be
|
||||
* delivered to the service, it will be called with a null intent
|
||||
* object, so you must take care to check for this.
|
||||
*
|
||||
* <p>This mode makes sense for things that will be explicitly started
|
||||
* and stopped to run for arbitrary periods of time, such as a service
|
||||
* performing background music playback.
|
||||
*/
|
||||
public static final int START_STICKY = 1;
|
||||
|
||||
/**
|
||||
* Constant to return from {@link #onStartCommand}: if this service's
|
||||
* process is killed while it is started (after returning from
|
||||
* {@link #onStartCommand}), and there are no new start intents to
|
||||
* deliver to it, then take the service out of the started state and
|
||||
* don't recreate until a future explicit call to
|
||||
* {@link Context#startService Context.startService(Intent)}. The
|
||||
* service will not receive a {@link #onStartCommand(Intent, int, int)}
|
||||
* call with a null Intent because it will not be re-started if there
|
||||
* are no pending Intents to deliver.
|
||||
*
|
||||
* <p>This mode makes sense for things that want to do some work as a
|
||||
* result of being started, but can be stopped when under memory pressure
|
||||
* and will explicit start themselves again later to do more work. An
|
||||
* example of such a service would be one that polls for data from
|
||||
* a server: it could schedule an alarm to poll every N minutes by having
|
||||
* the alarm start its service. When its {@link #onStartCommand} is
|
||||
* called from the alarm, it schedules a new alarm for N minutes later,
|
||||
* and spawns a thread to do its networking. If its process is killed
|
||||
* while doing that check, the service will not be restarted until the
|
||||
* alarm goes off.
|
||||
*/
|
||||
public static final int START_NOT_STICKY = 2;
|
||||
/**
|
||||
* Constant to return from {@link #onStartCommand}: if this service's
|
||||
* process is killed while it is started (after returning from
|
||||
* {@link #onStartCommand}), then it will be scheduled for a restart
|
||||
* and the last delivered Intent re-delivered to it again via
|
||||
* {@link #onStartCommand}. This Intent will remain scheduled for
|
||||
* redelivery until the service calls {@link #stopSelf(int)} with the
|
||||
* start ID provided to {@link #onStartCommand}. The
|
||||
* service will not receive a {@link #onStartCommand(Intent, int, int)}
|
||||
* call with a null Intent because it will will only be re-started if
|
||||
* it is not finished processing all Intents sent to it (and any such
|
||||
* pending events will be delivered at the point of restart).
|
||||
*/
|
||||
public static final int START_REDELIVER_INTENT = 3;
|
||||
/** @hide */
|
||||
@IntDef(flag = false,
|
||||
value = {
|
||||
START_STICKY_COMPATIBILITY,
|
||||
START_STICKY,
|
||||
START_NOT_STICKY,
|
||||
START_REDELIVER_INTENT,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface StartResult {}
|
||||
/**
|
||||
* Special constant for reporting that we are done processing
|
||||
* {@link #onTaskRemoved(Intent)}.
|
||||
* @hide
|
||||
*/
|
||||
public static final int START_TASK_REMOVED_COMPLETE = 1000;
|
||||
/**
|
||||
* This flag is set in {@link #onStartCommand} if the Intent is a
|
||||
* re-delivery of a previously delivered intent, because the service
|
||||
* had previously returned {@link #START_REDELIVER_INTENT} but had been
|
||||
* killed before calling {@link #stopSelf(int)} for that Intent.
|
||||
*/
|
||||
public static final int START_FLAG_REDELIVERY = 0x0001;
|
||||
|
||||
/**
|
||||
* This flag is set in {@link #onStartCommand} if the Intent is a
|
||||
* retry because the original attempt never got to or returned from
|
||||
* {@link #onStartCommand(Intent, int, int)}.
|
||||
*/
|
||||
public static final int START_FLAG_RETRY = 0x0002;
|
||||
/** @hide */
|
||||
@IntDef(flag = true,
|
||||
value = {
|
||||
START_FLAG_REDELIVERY,
|
||||
START_FLAG_RETRY,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface StartArgFlags {}
|
||||
/**
|
||||
* Called by the system every time a client explicitly starts the service by calling
|
||||
* {@link android.content.Context#startService}, providing the arguments it supplied and a
|
||||
* unique integer token representing the start request. Do not call this method directly.
|
||||
*
|
||||
* <p>For backwards compatibility, the default implementation calls
|
||||
* {@link #onStart} and returns either {@link #START_STICKY}
|
||||
* or {@link #START_STICKY_COMPATIBILITY}.
|
||||
*
|
||||
* <p>If you need your application to run on platform versions prior to API
|
||||
* level 5, you can use the following model to handle the older {@link #onStart}
|
||||
* callback in that case. The <code>handleCommand</code> method is implemented by
|
||||
* you as appropriate:
|
||||
*
|
||||
* {@sample development/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java
|
||||
* start_compatibility}
|
||||
*
|
||||
* <p class="caution">Note that the system calls this on your
|
||||
* service's main thread. A service's main thread is the same
|
||||
* thread where UI operations take place for Activities running in the
|
||||
* same process. You should always avoid stalling the main
|
||||
* thread's event loop. When doing long-running operations,
|
||||
* network calls, or heavy disk I/O, you should kick off a new
|
||||
* thread, or use {@link android.os.AsyncTask}.</p>
|
||||
*
|
||||
* @param intent The Intent supplied to {@link android.content.Context#startService},
|
||||
* as given. This may be null if the service is being restarted after
|
||||
* its process has gone away, and it had previously returned anything
|
||||
* except {@link #START_STICKY_COMPATIBILITY}.
|
||||
* @param flags Additional data about this start request. Currently either
|
||||
* 0, {@link #START_FLAG_REDELIVERY}, or {@link #START_FLAG_RETRY}.
|
||||
* @param startId A unique integer representing this specific request to
|
||||
* start. Use with {@link #stopSelfResult(int)}.
|
||||
*
|
||||
* @return The return value indicates what semantics the system should
|
||||
* use for the service's current started state. It may be one of the
|
||||
* constants associated with the {@link #START_CONTINUATION_MASK} bits.
|
||||
*
|
||||
* @see #stopSelfResult(int)
|
||||
*/
|
||||
public @StartResult int onStartCommand(Intent intent, @StartArgFlags int flags, int startId) {
|
||||
onStart(intent, startId);
|
||||
return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the system to notify a Service that it is no longer used and is being removed. The
|
||||
* service should clean up any resources it holds (threads, registered
|
||||
* receivers, etc) at this point. Upon return, there will be no more calls
|
||||
* in to this Service object and it is effectively dead. Do not call this method directly.
|
||||
*/
|
||||
public void onDestroy() {
|
||||
}
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
}
|
||||
|
||||
public void onLowMemory() {
|
||||
}
|
||||
public void onTrimMemory(int level) {
|
||||
}
|
||||
/**
|
||||
* Return the communication channel to the service. May return null if
|
||||
* clients can not bind to the service. The returned
|
||||
* {@link android.os.IBinder} is usually for a complex interface
|
||||
* that has been <a href="{@docRoot}guide/components/aidl.html">described using
|
||||
* aidl</a>.
|
||||
*
|
||||
* <p><em>Note that unlike other application components, calls on to the
|
||||
* IBinder interface returned here may not happen on the main thread
|
||||
* of the process</em>. More information about the main thread can be found in
|
||||
* <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html">Processes and
|
||||
* Threads</a>.</p>
|
||||
*
|
||||
* @param intent The Intent that was used to bind to this service,
|
||||
* as given to {@link android.content.Context#bindService
|
||||
* Context.bindService}. Note that any extras that were included with
|
||||
* the Intent at that point will <em>not</em> be seen here.
|
||||
*
|
||||
* @return Return an IBinder through which clients can call on to the
|
||||
* service.
|
||||
*/
|
||||
@Nullable
|
||||
public abstract IBinder onBind(Intent intent);
|
||||
/**
|
||||
* Called when all clients have disconnected from a particular interface
|
||||
* published by the service. The default implementation does nothing and
|
||||
* returns false.
|
||||
*
|
||||
* @param intent The Intent that was used to bind to this service,
|
||||
* as given to {@link android.content.Context#bindService
|
||||
* Context.bindService}. Note that any extras that were included with
|
||||
* the Intent at that point will <em>not</em> be seen here.
|
||||
*
|
||||
* @return Return true if you would like to have the service's
|
||||
* {@link #onRebind} method later called when new clients bind to it.
|
||||
*/
|
||||
public boolean onUnbind(Intent intent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when new clients have connected to the service, after it had
|
||||
* previously been notified that all had disconnected in its
|
||||
* {@link #onUnbind}. This will only be called if the implementation
|
||||
* of {@link #onUnbind} was overridden to return true.
|
||||
*
|
||||
* @param intent The Intent that was used to bind to this service,
|
||||
* as given to {@link android.content.Context#bindService
|
||||
* Context.bindService}. Note that any extras that were included with
|
||||
* the Intent at that point will <em>not</em> be seen here.
|
||||
*/
|
||||
public void onRebind(Intent intent) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called if the service is currently running and the user has
|
||||
* removed a task that comes from the service's application. If you have
|
||||
* set {@link android.content.pm.ServiceInfo#FLAG_STOP_WITH_TASK ServiceInfo.FLAG_STOP_WITH_TASK}
|
||||
* then you will not receive this callback; instead, the service will simply
|
||||
* be stopped.
|
||||
*
|
||||
* @param rootIntent The original root Intent that was used to launch
|
||||
* the task that is being removed.
|
||||
*/
|
||||
public void onTaskRemoved(Intent rootIntent) {
|
||||
}
|
||||
/**
|
||||
* Stop the service, if it was previously started. This is the same as
|
||||
* calling {@link android.content.Context#stopService} for this particular service.
|
||||
*
|
||||
* @see #stopSelfResult(int)
|
||||
*/
|
||||
public final void stopSelf() {
|
||||
stopSelf(-1);
|
||||
}
|
||||
/**
|
||||
* Old version of {@link #stopSelfResult} that doesn't return a result.
|
||||
*
|
||||
* @see #stopSelfResult
|
||||
*/
|
||||
public final void stopSelf(int startId) {
|
||||
serviceSupport.stopSelf(this);
|
||||
//TODO Do something with startId
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the service if the most recent time it was started was
|
||||
* <var>startId</var>. This is the same as calling {@link
|
||||
* android.content.Context#stopService} for this particular service but allows you to
|
||||
* safely avoid stopping if there is a start request from a client that you
|
||||
* haven't yet seen in {@link #onStart}.
|
||||
*
|
||||
* <p><em>Be careful about ordering of your calls to this function.</em>.
|
||||
* If you call this function with the most-recently received ID before
|
||||
* you have called it for previously received IDs, the service will be
|
||||
* immediately stopped anyway. If you may end up processing IDs out
|
||||
* of order (such as by dispatching them on separate threads), then you
|
||||
* are responsible for stopping them in the same order you received them.</p>
|
||||
*
|
||||
* @param startId The most recent start identifier received in {@link
|
||||
* #onStart}.
|
||||
* @return Returns true if the startId matches the last start request
|
||||
* and the service will be stopped, else false.
|
||||
*
|
||||
* @see #stopSelf()
|
||||
*/
|
||||
public final boolean stopSelfResult(int startId) {
|
||||
stopSelf(startId);
|
||||
//TODO Actually return result maybe
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This is a now a no-op, use
|
||||
* {@link #startForeground(int, Notification)} instead. This method
|
||||
* has been turned into a no-op rather than simply being deprecated
|
||||
* because analysis of numerous poorly behaving devices has shown that
|
||||
* increasingly often the trouble is being caused in part by applications
|
||||
* that are abusing it. Thus, given a choice between introducing
|
||||
* problems in existing applications using this API (by allowing them to
|
||||
* be killed when they would like to avoid it), vs allowing the performance
|
||||
* of the entire system to be decreased, this method was deemed less
|
||||
* important.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Deprecated
|
||||
public final void setForeground(boolean isForeground) {
|
||||
Log.w(TAG, "setForeground: ignoring old API call on " + getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Make this service run in the foreground, supplying the ongoing
|
||||
* notification to be shown to the user while in this state.
|
||||
* By default services are background, meaning that if the system needs to
|
||||
* kill them to reclaim more memory (such as to display a large page in a
|
||||
* web browser), they can be killed without too much harm. You can set this
|
||||
* flag if killing your service would be disruptive to the user, such as
|
||||
* if your service is performing background music playback, so the user
|
||||
* would notice if their music stopped playing.
|
||||
*
|
||||
* <p>If you need your application to run on platform versions prior to API
|
||||
* level 5, you can use the following model to call the the older setForeground()
|
||||
* or this modern method as appropriate:
|
||||
*
|
||||
* {@sample development/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java
|
||||
* foreground_compatibility}
|
||||
*
|
||||
* @param id The identifier for this notification as per
|
||||
* {@link NotificationManager#notify(int, Notification)
|
||||
* NotificationManager.notify(int, Notification)}; must not be 0.
|
||||
* @param notification The Notification to be displayed.
|
||||
*
|
||||
* @see #stopForeground(boolean)
|
||||
*/
|
||||
public final void startForeground(int id, Notification notification) {
|
||||
throw new NotImplementedError("TODO");
|
||||
}
|
||||
|
||||
/**
|
||||
* Synonym for {@link #stopForeground(int)}.
|
||||
* @param removeNotification If true, the {@link #STOP_FOREGROUND_REMOVE} flag
|
||||
* will be supplied.
|
||||
* @see #stopForeground(int)
|
||||
* @see #startForeground(int, Notification)
|
||||
*/
|
||||
public final void stopForeground(boolean removeNotification) {
|
||||
stopForeground(removeNotification ? STOP_FOREGROUND_REMOVE : 0);
|
||||
}
|
||||
/**
|
||||
* Remove this service from foreground state, allowing it to be killed if
|
||||
* more memory is needed.
|
||||
* @param flags Additional behavior options: {@link #STOP_FOREGROUND_REMOVE},
|
||||
* {@link #STOP_FOREGROUND_DETACH}.
|
||||
* @see #startForeground(int, Notification)
|
||||
*/
|
||||
public final void stopForeground(@StopForegroundFlags int flags) {
|
||||
throw new NotImplementedError("TODO");
|
||||
}
|
||||
/**
|
||||
* Print the Service's state into the given stream. This gets invoked if
|
||||
* you run "adb shell dumpsys activity service <yourservicename>"
|
||||
* (note that for this command to work, the service must be running, and
|
||||
* you must specify a fully-qualified service name).
|
||||
* This is distinct from "dumpsys <servicename>", which only works for
|
||||
* named system services and which invokes the {@link IBinder#dump} method
|
||||
* on the {@link IBinder} interface registered with ServiceManager.
|
||||
*
|
||||
* @param fd The raw file descriptor that the dump is being sent to.
|
||||
* @param writer The PrintWriter to which you should dump your state. This will be
|
||||
* closed for you after you return.
|
||||
* @param args additional arguments to the dump request.
|
||||
*/
|
||||
protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
|
||||
writer.println("nothing to dump");
|
||||
}
|
||||
// ------------------ Internal API ------------------
|
||||
|
||||
|
||||
final String getClassName() {
|
||||
return mClassName;
|
||||
}
|
||||
// set by the thread after the constructor and before onCreate(Bundle icicle) is called.
|
||||
private String mClassName = null;
|
||||
private IBinder mToken = null;
|
||||
private Application mApplication = null;
|
||||
private boolean mStartCompatibility = false;
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.arch.persistence.db;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A basic implementation of {@link SupportSQLiteQuery} which receives a query and its args and
|
||||
* binds args based on the passed in Object type.
|
||||
*/
|
||||
public final class SimpleSQLiteQuery implements SupportSQLiteQuery {
|
||||
private final String mQuery;
|
||||
@Nullable
|
||||
private final Object[] mBindArgs;
|
||||
|
||||
/**
|
||||
* Creates an SQL query with the sql string and the bind arguments.
|
||||
*
|
||||
* @param query The query string, can include bind arguments (.e.g ?).
|
||||
* @param bindArgs The bind argument value that will replace the placeholders in the query.
|
||||
*/
|
||||
public SimpleSQLiteQuery(String query, @Nullable Object[] bindArgs) {
|
||||
mQuery = query;
|
||||
mBindArgs = bindArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SQL query without any bind arguments.
|
||||
*
|
||||
* @param query The SQL query to execute. Cannot include bind parameters.
|
||||
*/
|
||||
public SimpleSQLiteQuery(String query) {
|
||||
this(query, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the given arguments into the given sqlite statement.
|
||||
*
|
||||
* @param statement The sqlite statement
|
||||
* @param bindArgs The list of bind arguments
|
||||
*/
|
||||
public static void bind(SupportSQLiteProgram statement, Object[] bindArgs) {
|
||||
if (bindArgs == null) {
|
||||
return;
|
||||
}
|
||||
final int limit = bindArgs.length;
|
||||
for (int i = 0; i < limit; i++) {
|
||||
final Object arg = bindArgs[i];
|
||||
bind(statement, i + 1, arg);
|
||||
}
|
||||
}
|
||||
|
||||
private static void bind(SupportSQLiteProgram statement, int index, Object arg) {
|
||||
// extracted from android.database.sqlite.SQLiteConnection
|
||||
if (arg == null) {
|
||||
statement.bindNull(index);
|
||||
} else if (arg instanceof byte[]) {
|
||||
statement.bindBlob(index, (byte[]) arg);
|
||||
} else if (arg instanceof Float) {
|
||||
statement.bindDouble(index, (Float) arg);
|
||||
} else if (arg instanceof Double) {
|
||||
statement.bindDouble(index, (Double) arg);
|
||||
} else if (arg instanceof Long) {
|
||||
statement.bindLong(index, (Long) arg);
|
||||
} else if (arg instanceof Integer) {
|
||||
statement.bindLong(index, (Integer) arg);
|
||||
} else if (arg instanceof Short) {
|
||||
statement.bindLong(index, (Short) arg);
|
||||
} else if (arg instanceof Byte) {
|
||||
statement.bindLong(index, (Byte) arg);
|
||||
} else if (arg instanceof String) {
|
||||
statement.bindString(index, (String) arg);
|
||||
} else if (arg instanceof Boolean) {
|
||||
statement.bindLong(index, ((Boolean) arg) ? 1 : 0);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Cannot bind " + arg + " at index " + index
|
||||
+ " Supported types: null, byte[], float, double, long, int, short, byte,"
|
||||
+ " string");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql() {
|
||||
return mQuery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindTo(SupportSQLiteProgram statement) {
|
||||
bind(statement, mBindArgs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArgCount() {
|
||||
return mBindArgs == null ? 0 : mBindArgs.length;
|
||||
}
|
||||
}
|
@ -0,0 +1,604 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.arch.persistence.db;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.SQLException;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteTransactionListener;
|
||||
import android.os.Build;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.OperationCanceledException;
|
||||
import android.util.Pair;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* A database abstraction which removes the framework dependency and allows swapping underlying
|
||||
* sql versions. It mimics the behavior of {@link android.database.sqlite.SQLiteDatabase}
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface SupportSQLiteDatabase extends Closeable {
|
||||
/**
|
||||
* Compiles the given SQL statement.
|
||||
*
|
||||
* @param sql The sql query.
|
||||
* @return Compiled statement.
|
||||
*/
|
||||
SupportSQLiteStatement compileStatement(String sql);
|
||||
|
||||
/**
|
||||
* Begins a transaction in EXCLUSIVE mode.
|
||||
* <p>
|
||||
* Transactions can be nested.
|
||||
* When the outer transaction is ended all of
|
||||
* the work done in that transaction and all of the nested transactions will be committed or
|
||||
* rolled back. The changes will be rolled back if any transaction is ended without being
|
||||
* marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
|
||||
* </p>
|
||||
* <p>Here is the standard idiom for transactions:
|
||||
*
|
||||
* <pre>
|
||||
* db.beginTransaction();
|
||||
* try {
|
||||
* ...
|
||||
* db.setTransactionSuccessful();
|
||||
* } finally {
|
||||
* db.endTransaction();
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
void beginTransaction();
|
||||
|
||||
/**
|
||||
* Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
|
||||
* the outer transaction is ended all of the work done in that transaction
|
||||
* and all of the nested transactions will be committed or rolled back. The
|
||||
* changes will be rolled back if any transaction is ended without being
|
||||
* marked as clean (by calling setTransactionSuccessful). Otherwise they
|
||||
* will be committed.
|
||||
* <p>
|
||||
* Here is the standard idiom for transactions:
|
||||
*
|
||||
* <pre>
|
||||
* db.beginTransactionNonExclusive();
|
||||
* try {
|
||||
* ...
|
||||
* db.setTransactionSuccessful();
|
||||
* } finally {
|
||||
* db.endTransaction();
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
void beginTransactionNonExclusive();
|
||||
|
||||
/**
|
||||
* Begins a transaction in EXCLUSIVE mode.
|
||||
* <p>
|
||||
* Transactions can be nested.
|
||||
* When the outer transaction is ended all of
|
||||
* the work done in that transaction and all of the nested transactions will be committed or
|
||||
* rolled back. The changes will be rolled back if any transaction is ended without being
|
||||
* marked as clean (by calling setTransactionSuccessful). Otherwise they will be committed.
|
||||
* </p>
|
||||
* <p>Here is the standard idiom for transactions:
|
||||
*
|
||||
* <pre>
|
||||
* db.beginTransactionWithListener(listener);
|
||||
* try {
|
||||
* ...
|
||||
* db.setTransactionSuccessful();
|
||||
* } finally {
|
||||
* db.endTransaction();
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param transactionListener listener that should be notified when the transaction begins,
|
||||
* commits, or is rolled back, either explicitly or by a call to
|
||||
* {@link #yieldIfContendedSafely}.
|
||||
*/
|
||||
void beginTransactionWithListener(SQLiteTransactionListener transactionListener);
|
||||
|
||||
/**
|
||||
* Begins a transaction in IMMEDIATE mode. Transactions can be nested. When
|
||||
* the outer transaction is ended all of the work done in that transaction
|
||||
* and all of the nested transactions will be committed or rolled back. The
|
||||
* changes will be rolled back if any transaction is ended without being
|
||||
* marked as clean (by calling setTransactionSuccessful). Otherwise they
|
||||
* will be committed.
|
||||
* <p>
|
||||
* Here is the standard idiom for transactions:
|
||||
*
|
||||
* <pre>
|
||||
* db.beginTransactionWithListenerNonExclusive(listener);
|
||||
* try {
|
||||
* ...
|
||||
* db.setTransactionSuccessful();
|
||||
* } finally {
|
||||
* db.endTransaction();
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param transactionListener listener that should be notified when the
|
||||
* transaction begins, commits, or is rolled back, either
|
||||
* explicitly or by a call to {@link #yieldIfContendedSafely}.
|
||||
*/
|
||||
void beginTransactionWithListenerNonExclusive(SQLiteTransactionListener transactionListener);
|
||||
|
||||
/**
|
||||
* End a transaction. See beginTransaction for notes about how to use this and when transactions
|
||||
* are committed and rolled back.
|
||||
*/
|
||||
void endTransaction();
|
||||
|
||||
/**
|
||||
* Marks the current transaction as successful. Do not do any more database work between
|
||||
* calling this and calling endTransaction. Do as little non-database work as possible in that
|
||||
* situation too. If any errors are encountered between this and endTransaction the transaction
|
||||
* will still be committed.
|
||||
*
|
||||
* @throws IllegalStateException if the current thread is not in a transaction or the
|
||||
* transaction is already marked as successful.
|
||||
*/
|
||||
void setTransactionSuccessful();
|
||||
|
||||
/**
|
||||
* Returns true if the current thread has a transaction pending.
|
||||
*
|
||||
* @return True if the current thread is in a transaction.
|
||||
*/
|
||||
boolean inTransaction();
|
||||
|
||||
/**
|
||||
* Returns true if the current thread is holding an active connection to the database.
|
||||
* <p>
|
||||
* The name of this method comes from a time when having an active connection
|
||||
* to the database meant that the thread was holding an actual lock on the
|
||||
* database. Nowadays, there is no longer a true "database lock" although threads
|
||||
* may block if they cannot acquire a database connection to perform a
|
||||
* particular operation.
|
||||
* </p>
|
||||
*
|
||||
* @return True if the current thread is holding an active connection to the database.
|
||||
*/
|
||||
boolean isDbLockedByCurrentThread();
|
||||
|
||||
/**
|
||||
* Temporarily end the transaction to let other threads run. The transaction is assumed to be
|
||||
* successful so far. Do not call setTransactionSuccessful before calling this. When this
|
||||
* returns a new transaction will have been created but not marked as successful. This assumes
|
||||
* that there are no nested transactions (beginTransaction has only been called once) and will
|
||||
* throw an exception if that is not the case.
|
||||
*
|
||||
* @return true if the transaction was yielded
|
||||
*/
|
||||
boolean yieldIfContendedSafely();
|
||||
|
||||
/**
|
||||
* Temporarily end the transaction to let other threads run. The transaction is assumed to be
|
||||
* successful so far. Do not call setTransactionSuccessful before calling this. When this
|
||||
* returns a new transaction will have been created but not marked as successful. This assumes
|
||||
* that there are no nested transactions (beginTransaction has only been called once) and will
|
||||
* throw an exception if that is not the case.
|
||||
*
|
||||
* @param sleepAfterYieldDelay if > 0, sleep this long before starting a new transaction if
|
||||
* the lock was actually yielded. This will allow other background
|
||||
* threads to make some
|
||||
* more progress than they would if we started the transaction
|
||||
* immediately.
|
||||
* @return true if the transaction was yielded
|
||||
*/
|
||||
boolean yieldIfContendedSafely(long sleepAfterYieldDelay);
|
||||
|
||||
/**
|
||||
* Gets the database version.
|
||||
*
|
||||
* @return the database version
|
||||
*/
|
||||
int getVersion();
|
||||
|
||||
/**
|
||||
* Sets the database version.
|
||||
*
|
||||
* @param version the new database version
|
||||
*/
|
||||
void setVersion(int version);
|
||||
|
||||
/**
|
||||
* Returns the maximum size the database may grow to.
|
||||
*
|
||||
* @return the new maximum database size
|
||||
*/
|
||||
long getMaximumSize();
|
||||
|
||||
/**
|
||||
* Sets the maximum size the database will grow to. The maximum size cannot
|
||||
* be set below the current size.
|
||||
*
|
||||
* @param numBytes the maximum database size, in bytes
|
||||
* @return the new maximum database size
|
||||
*/
|
||||
long setMaximumSize(long numBytes);
|
||||
|
||||
/**
|
||||
* Returns the current database page size, in bytes.
|
||||
*
|
||||
* @return the database page size, in bytes
|
||||
*/
|
||||
long getPageSize();
|
||||
|
||||
/**
|
||||
* Sets the database page size. The page size must be a power of two. This
|
||||
* method does not work if any data has been written to the database file,
|
||||
* and must be called right after the database has been created.
|
||||
*
|
||||
* @param numBytes the database page size, in bytes
|
||||
*/
|
||||
void setPageSize(long numBytes);
|
||||
|
||||
/**
|
||||
* Runs the given query on the database. If you would like to have typed bind arguments,
|
||||
* use {@link #query(SupportSQLiteQuery)}.
|
||||
*
|
||||
* @param query The SQL query that includes the query and can bind into a given compiled
|
||||
* program.
|
||||
* @return A {@link Cursor} object, which is positioned before the first entry. Note that
|
||||
* {@link Cursor}s are not synchronized, see the documentation for more details.
|
||||
* @see #query(SupportSQLiteQuery)
|
||||
*/
|
||||
Cursor query(String query);
|
||||
|
||||
/**
|
||||
* Runs the given query on the database. If you would like to have bind arguments,
|
||||
* use {@link #query(SupportSQLiteQuery)}.
|
||||
*
|
||||
* @param query The SQL query that includes the query and can bind into a given compiled
|
||||
* program.
|
||||
* @param bindArgs The query arguments to bind.
|
||||
* @return A {@link Cursor} object, which is positioned before the first entry. Note that
|
||||
* {@link Cursor}s are not synchronized, see the documentation for more details.
|
||||
* @see #query(SupportSQLiteQuery)
|
||||
*/
|
||||
Cursor query(String query, Object[] bindArgs);
|
||||
|
||||
/**
|
||||
* Runs the given query on the database.
|
||||
* <p>
|
||||
* This class allows using type safe sql program bindings while running queries.
|
||||
*
|
||||
* @param query The SQL query that includes the query and can bind into a given compiled
|
||||
* program.
|
||||
* @return A {@link Cursor} object, which is positioned before the first entry. Note that
|
||||
* {@link Cursor}s are not synchronized, see the documentation for more details.
|
||||
* @see SimpleSQLiteQuery
|
||||
*/
|
||||
Cursor query(SupportSQLiteQuery query);
|
||||
|
||||
/**
|
||||
* Runs the given query on the database.
|
||||
* <p>
|
||||
* This class allows using type safe sql program bindings while running queries.
|
||||
*
|
||||
* @param query The SQL query that includes the query and can bind into a given compiled
|
||||
* program.
|
||||
* @param cancellationSignal A signal to cancel the operation in progress, or null if none.
|
||||
* If the operation is canceled, then {@link OperationCanceledException} will be thrown
|
||||
* when the query is executed.
|
||||
* @return A {@link Cursor} object, which is positioned before the first entry. Note that
|
||||
* {@link Cursor}s are not synchronized, see the documentation for more details.
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
|
||||
Cursor query(SupportSQLiteQuery query, CancellationSignal cancellationSignal);
|
||||
|
||||
/**
|
||||
* Convenience method for inserting a row into the database.
|
||||
*
|
||||
* @param table the table to insert the row into
|
||||
* @param values this map contains the initial column values for the
|
||||
* row. The keys should be the column names and the values the
|
||||
* column values
|
||||
* @param conflictAlgorithm for insert conflict resolver. One of
|
||||
* {@link SQLiteDatabase#CONFLICT_NONE}, {@link SQLiteDatabase#CONFLICT_ROLLBACK},
|
||||
* {@link SQLiteDatabase#CONFLICT_ABORT}, {@link SQLiteDatabase#CONFLICT_FAIL},
|
||||
* {@link SQLiteDatabase#CONFLICT_IGNORE}, {@link SQLiteDatabase#CONFLICT_REPLACE}.
|
||||
* @return the row ID of the newly inserted row, or -1 if an error occurred
|
||||
* @throws SQLException If the insert fails
|
||||
*/
|
||||
long insert(String table, int conflictAlgorithm, ContentValues values) throws SQLException;
|
||||
|
||||
/**
|
||||
* Convenience method for deleting rows in the database.
|
||||
*
|
||||
* @param table the table to delete from
|
||||
* @param whereClause the optional WHERE clause to apply when deleting.
|
||||
* Passing null will delete all rows.
|
||||
* @param whereArgs You may include ?s in the where clause, which
|
||||
* will be replaced by the values from whereArgs. The values
|
||||
* will be bound as Strings.
|
||||
* @return the number of rows affected if a whereClause is passed in, 0
|
||||
* otherwise. To remove all rows and get a count pass "1" as the
|
||||
* whereClause.
|
||||
*/
|
||||
int delete(String table, String whereClause, Object[] whereArgs);
|
||||
|
||||
/**
|
||||
* Convenience method for updating rows in the database.
|
||||
*
|
||||
* @param table the table to update in
|
||||
* @param conflictAlgorithm for update conflict resolver. One of
|
||||
* {@link SQLiteDatabase#CONFLICT_NONE}, {@link SQLiteDatabase#CONFLICT_ROLLBACK},
|
||||
* {@link SQLiteDatabase#CONFLICT_ABORT}, {@link SQLiteDatabase#CONFLICT_FAIL},
|
||||
* {@link SQLiteDatabase#CONFLICT_IGNORE}, {@link SQLiteDatabase#CONFLICT_REPLACE}.
|
||||
* @param values a map from column names to new column values. null is a
|
||||
* valid value that will be translated to NULL.
|
||||
* @param whereClause the optional WHERE clause to apply when updating.
|
||||
* Passing null will update all rows.
|
||||
* @param whereArgs You may include ?s in the where clause, which
|
||||
* will be replaced by the values from whereArgs. The values
|
||||
* will be bound as Strings.
|
||||
* @return the number of rows affected
|
||||
*/
|
||||
int update(String table, int conflictAlgorithm,
|
||||
ContentValues values, String whereClause, Object[] whereArgs);
|
||||
|
||||
/**
|
||||
* Execute a single SQL statement that does not return any data.
|
||||
* <p>
|
||||
* When using {@link #enableWriteAheadLogging()}, journal_mode is
|
||||
* automatically managed by this class. So, do not set journal_mode
|
||||
* using "PRAGMA journal_mode'<value>" statement if your app is using
|
||||
* {@link #enableWriteAheadLogging()}
|
||||
* </p>
|
||||
*
|
||||
* @param sql the SQL statement to be executed. Multiple statements separated by semicolons are
|
||||
* not supported.
|
||||
* @throws SQLException if the SQL string is invalid
|
||||
* @see #query(SupportSQLiteQuery)
|
||||
*/
|
||||
void execSQL(String sql) throws SQLException;
|
||||
|
||||
/**
|
||||
* Execute a single SQL statement that does not return any data.
|
||||
* <p>
|
||||
* When using {@link #enableWriteAheadLogging()}, journal_mode is
|
||||
* automatically managed by this class. So, do not set journal_mode
|
||||
* using "PRAGMA journal_mode'<value>" statement if your app is using
|
||||
* {@link #enableWriteAheadLogging()}
|
||||
* </p>
|
||||
*
|
||||
* @param sql the SQL statement to be executed. Multiple statements separated by semicolons
|
||||
* are
|
||||
* not supported.
|
||||
* @param bindArgs only byte[], String, Long and Double are supported in selectionArgs.
|
||||
* @throws SQLException if the SQL string is invalid
|
||||
* @see #query(SupportSQLiteQuery)
|
||||
*/
|
||||
void execSQL(String sql, Object[] bindArgs) throws SQLException;
|
||||
|
||||
/**
|
||||
* Returns true if the database is opened as read only.
|
||||
*
|
||||
* @return True if database is opened as read only.
|
||||
*/
|
||||
boolean isReadOnly();
|
||||
|
||||
/**
|
||||
* Returns true if the database is currently open.
|
||||
*
|
||||
* @return True if the database is currently open (has not been closed).
|
||||
*/
|
||||
boolean isOpen();
|
||||
|
||||
/**
|
||||
* Returns true if the new version code is greater than the current database version.
|
||||
*
|
||||
* @param newVersion The new version code.
|
||||
* @return True if the new version code is greater than the current database version.
|
||||
*/
|
||||
boolean needUpgrade(int newVersion);
|
||||
|
||||
/**
|
||||
* Gets the path to the database file.
|
||||
*
|
||||
* @return The path to the database file.
|
||||
*/
|
||||
String getPath();
|
||||
|
||||
/**
|
||||
* Sets the locale for this database. Does nothing if this database has
|
||||
* the {@link SQLiteDatabase#NO_LOCALIZED_COLLATORS} flag set or was opened read only.
|
||||
*
|
||||
* @param locale The new locale.
|
||||
* @throws SQLException if the locale could not be set. The most common reason
|
||||
* for this is that there is no collator available for the locale you
|
||||
* requested.
|
||||
* In this case the database remains unchanged.
|
||||
*/
|
||||
void setLocale(Locale locale);
|
||||
|
||||
/**
|
||||
* Sets the maximum size of the prepared-statement cache for this database.
|
||||
* (size of the cache = number of compiled-sql-statements stored in the cache).
|
||||
* <p>
|
||||
* Maximum cache size can ONLY be increased from its current size (default = 10).
|
||||
* If this method is called with smaller size than the current maximum value,
|
||||
* then IllegalStateException is thrown.
|
||||
* <p>
|
||||
* This method is thread-safe.
|
||||
*
|
||||
* @param cacheSize the size of the cache. can be (0 to
|
||||
* {@link SQLiteDatabase#MAX_SQL_CACHE_SIZE})
|
||||
* @throws IllegalStateException if input cacheSize gt;
|
||||
* {@link SQLiteDatabase#MAX_SQL_CACHE_SIZE}.
|
||||
*/
|
||||
void setMaxSqlCacheSize(int cacheSize);
|
||||
|
||||
/**
|
||||
* Sets whether foreign key constraints are enabled for the database.
|
||||
* <p>
|
||||
* By default, foreign key constraints are not enforced by the database.
|
||||
* This method allows an application to enable foreign key constraints.
|
||||
* It must be called each time the database is opened to ensure that foreign
|
||||
* key constraints are enabled for the session.
|
||||
* </p><p>
|
||||
* A good time to call this method is right after calling {@code #openOrCreateDatabase}
|
||||
* or in the {@link SupportSQLiteOpenHelper.Callback#onConfigure} callback.
|
||||
* </p><p>
|
||||
* When foreign key constraints are disabled, the database does not check whether
|
||||
* changes to the database will violate foreign key constraints. Likewise, when
|
||||
* foreign key constraints are disabled, the database will not execute cascade
|
||||
* delete or update triggers. As a result, it is possible for the database
|
||||
* state to become inconsistent. To perform a database integrity check,
|
||||
* call {@link #isDatabaseIntegrityOk}.
|
||||
* </p><p>
|
||||
* This method must not be called while a transaction is in progress.
|
||||
* </p><p>
|
||||
* See also <a href="http://sqlite.org/foreignkeys.html">SQLite Foreign Key Constraints</a>
|
||||
* for more details about foreign key constraint support.
|
||||
* </p>
|
||||
*
|
||||
* @param enable True to enable foreign key constraints, false to disable them.
|
||||
* @throws IllegalStateException if the are transactions is in progress
|
||||
* when this method is called.
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
|
||||
void setForeignKeyConstraintsEnabled(boolean enable);
|
||||
|
||||
/**
|
||||
* This method enables parallel execution of queries from multiple threads on the
|
||||
* same database. It does this by opening multiple connections to the database
|
||||
* and using a different database connection for each query. The database
|
||||
* journal mode is also changed to enable writes to proceed concurrently with reads.
|
||||
* <p>
|
||||
* When write-ahead logging is not enabled (the default), it is not possible for
|
||||
* reads and writes to occur on the database at the same time. Before modifying the
|
||||
* database, the writer implicitly acquires an exclusive lock on the database which
|
||||
* prevents readers from accessing the database until the write is completed.
|
||||
* </p><p>
|
||||
* In contrast, when write-ahead logging is enabled (by calling this method), write
|
||||
* operations occur in a separate log file which allows reads to proceed concurrently.
|
||||
* While a write is in progress, readers on other threads will perceive the state
|
||||
* of the database as it was before the write began. When the write completes, readers
|
||||
* on other threads will then perceive the new state of the database.
|
||||
* </p><p>
|
||||
* It is a good idea to enable write-ahead logging whenever a database will be
|
||||
* concurrently accessed and modified by multiple threads at the same time.
|
||||
* However, write-ahead logging uses significantly more memory than ordinary
|
||||
* journaling because there are multiple connections to the same database.
|
||||
* So if a database will only be used by a single thread, or if optimizing
|
||||
* concurrency is not very important, then write-ahead logging should be disabled.
|
||||
* </p><p>
|
||||
* After calling this method, execution of queries in parallel is enabled as long as
|
||||
* the database remains open. To disable execution of queries in parallel, either
|
||||
* call {@link #disableWriteAheadLogging} or close the database and reopen it.
|
||||
* </p><p>
|
||||
* The maximum number of connections used to execute queries in parallel is
|
||||
* dependent upon the device memory and possibly other properties.
|
||||
* </p><p>
|
||||
* If a query is part of a transaction, then it is executed on the same database handle the
|
||||
* transaction was begun.
|
||||
* </p><p>
|
||||
* Writers should use {@link #beginTransactionNonExclusive()} or
|
||||
* {@link #beginTransactionWithListenerNonExclusive(SQLiteTransactionListener)}
|
||||
* to start a transaction. Non-exclusive mode allows database file to be in readable
|
||||
* by other threads executing queries.
|
||||
* </p><p>
|
||||
* If the database has any attached databases, then execution of queries in parallel is NOT
|
||||
* possible. Likewise, write-ahead logging is not supported for read-only databases
|
||||
* or memory databases. In such cases, {@code enableWriteAheadLogging} returns false.
|
||||
* </p><p>
|
||||
* The best way to enable write-ahead logging is to pass the
|
||||
* {@link SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING} flag to
|
||||
* {@link SQLiteDatabase#openDatabase}. This is more efficient than calling
|
||||
* <code><pre>
|
||||
* SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
|
||||
* SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING,
|
||||
* myDatabaseErrorHandler);
|
||||
* db.enableWriteAheadLogging();
|
||||
* </pre></code>
|
||||
* </p><p>
|
||||
* Another way to enable write-ahead logging is to call {@code enableWriteAheadLogging}
|
||||
* after opening the database.
|
||||
* <code><pre>
|
||||
* SQLiteDatabase db = SQLiteDatabase.openDatabase("db_filename", cursorFactory,
|
||||
* SQLiteDatabase.CREATE_IF_NECESSARY, myDatabaseErrorHandler);
|
||||
* db.enableWriteAheadLogging();
|
||||
* </pre></code>
|
||||
* </p><p>
|
||||
* See also <a href="http://sqlite.org/wal.html">SQLite Write-Ahead Logging</a> for
|
||||
* more details about how write-ahead logging works.
|
||||
* </p>
|
||||
*
|
||||
* @return True if write-ahead logging is enabled.
|
||||
* @throws IllegalStateException if there are transactions in progress at the
|
||||
* time this method is called. WAL mode can only be changed when
|
||||
* there are no
|
||||
* transactions in progress.
|
||||
* @see SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING
|
||||
* @see #disableWriteAheadLogging
|
||||
*/
|
||||
boolean enableWriteAheadLogging();
|
||||
|
||||
/**
|
||||
* This method disables the features enabled by {@link #enableWriteAheadLogging()}.
|
||||
*
|
||||
* @throws IllegalStateException if there are transactions in progress at the
|
||||
* time this method is called. WAL mode can only be changed when
|
||||
* there are no
|
||||
* transactions in progress.
|
||||
* @see #enableWriteAheadLogging
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
|
||||
void disableWriteAheadLogging();
|
||||
|
||||
/**
|
||||
* Returns true if write-ahead logging has been enabled for this database.
|
||||
*
|
||||
* @return True if write-ahead logging has been enabled for this database.
|
||||
* @see #enableWriteAheadLogging
|
||||
* @see SQLiteDatabase#ENABLE_WRITE_AHEAD_LOGGING
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
|
||||
boolean isWriteAheadLoggingEnabled();
|
||||
|
||||
/**
|
||||
* Returns list of full path names of all attached databases including the main database
|
||||
* by executing 'pragma database_list' on the database.
|
||||
*
|
||||
* @return ArrayList of pairs of (database name, database file path) or null if the database
|
||||
* is not open.
|
||||
*/
|
||||
List<Pair<String, String>> getAttachedDbs();
|
||||
|
||||
/**
|
||||
* Runs 'pragma integrity_check' on the given database (and all the attached databases)
|
||||
* and returns true if the given database (and all its attached databases) pass integrity_check,
|
||||
* false otherwise.
|
||||
* <p>
|
||||
* If the result is false, then this method logs the errors reported by the integrity_check
|
||||
* command execution.
|
||||
* <p>
|
||||
* Note that 'pragma integrity_check' on a database can take a long time.
|
||||
*
|
||||
* @return true if the given database (and all its attached databases) pass integrity_check,
|
||||
* false otherwise.
|
||||
*/
|
||||
boolean isDatabaseIntegrityOk();
|
||||
}
|
@ -0,0 +1,389 @@
|
||||
package android.arch.persistence.db;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
// TODO Replace with androidx variant once Tachiyomi updates
|
||||
|
||||
/**
|
||||
* An interface to map the behavior of {@link android.database.sqlite.SQLiteOpenHelper}.
|
||||
* Note that since that class requires overriding certain methods, support implementation
|
||||
* uses {@link Factory#create(Configuration)} to create this and {@link Callback} to implement
|
||||
* the methods that should be overridden.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface SupportSQLiteOpenHelper {
|
||||
/**
|
||||
* Return the name of the SQLite database being opened, as given to
|
||||
* the constructor.
|
||||
*/
|
||||
String getDatabaseName();
|
||||
|
||||
/**
|
||||
* Enables or disables the use of write-ahead logging for the database.
|
||||
* <p>
|
||||
* Write-ahead logging cannot be used with read-only databases so the value of
|
||||
* this flag is ignored if the database is opened read-only.
|
||||
*
|
||||
* @param enabled True if write-ahead logging should be enabled, false if it
|
||||
* should be disabled.
|
||||
* @see SupportSQLiteDatabase#enableWriteAheadLogging()
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
|
||||
void setWriteAheadLoggingEnabled(boolean enabled);
|
||||
|
||||
/**
|
||||
* Create and/or open a database that will be used for reading and writing.
|
||||
* The first time this is called, the database will be opened and
|
||||
* {@link Callback#onCreate}, {@link Callback#onUpgrade} and/or {@link Callback#onOpen} will be
|
||||
* called.
|
||||
*
|
||||
* <p>Once opened successfully, the database is cached, so you can
|
||||
* call this method every time you need to write to the database.
|
||||
* (Make sure to call {@link #close} when you no longer need the database.)
|
||||
* Errors such as bad permissions or a full disk may cause this method
|
||||
* to fail, but future attempts may succeed if the problem is fixed.</p>
|
||||
*
|
||||
* <p class="caution">Database upgrade may take a long time, you
|
||||
* should not call this method from the application main thread, including
|
||||
* from {@link android.content.ContentProvider#onCreate ContentProvider.onCreate()}.
|
||||
*
|
||||
* @return a read/write database object valid until {@link #close} is called
|
||||
* @throws SQLiteException if the database cannot be opened for writing
|
||||
*/
|
||||
SupportSQLiteDatabase getWritableDatabase();
|
||||
|
||||
/**
|
||||
* Create and/or open a database. This will be the same object returned by
|
||||
* {@link #getWritableDatabase} unless some problem, such as a full disk,
|
||||
* requires the database to be opened read-only. In that case, a read-only
|
||||
* database object will be returned. If the problem is fixed, a future call
|
||||
* to {@link #getWritableDatabase} may succeed, in which case the read-only
|
||||
* database object will be closed and the read/write object will be returned
|
||||
* in the future.
|
||||
*
|
||||
* <p class="caution">Like {@link #getWritableDatabase}, this method may
|
||||
* take a long time to return, so you should not call it from the
|
||||
* application main thread, including from
|
||||
* {@link android.content.ContentProvider#onCreate ContentProvider.onCreate()}.
|
||||
*
|
||||
* @return a database object valid until {@link #getWritableDatabase}
|
||||
* or {@link #close} is called.
|
||||
* @throws SQLiteException if the database cannot be opened
|
||||
*/
|
||||
SupportSQLiteDatabase getReadableDatabase();
|
||||
|
||||
/**
|
||||
* Close any open database object.
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Factory class to create instances of {@link SupportSQLiteOpenHelper} using
|
||||
* {@link Configuration}.
|
||||
*/
|
||||
interface Factory {
|
||||
/**
|
||||
* Creates an instance of {@link SupportSQLiteOpenHelper} using the given configuration.
|
||||
*
|
||||
* @param configuration The configuration to use while creating the open helper.
|
||||
* @return A SupportSQLiteOpenHelper which can be used to open a database.
|
||||
*/
|
||||
SupportSQLiteOpenHelper create(Configuration configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles various lifecycle events for the SQLite connection, similar to
|
||||
* {@link android.database.sqlite.SQLiteOpenHelper}.
|
||||
*/
|
||||
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||
abstract class Callback {
|
||||
private static final String TAG = "SupportSQLite";
|
||||
/**
|
||||
* Version number of the database (starting at 1); if the database is older,
|
||||
* {@link SupportSQLiteOpenHelper.Callback#onUpgrade(SupportSQLiteDatabase, int, int)}
|
||||
* will be used to upgrade the database; if the database is newer,
|
||||
* {@link SupportSQLiteOpenHelper.Callback#onDowngrade(SupportSQLiteDatabase, int, int)}
|
||||
* will be used to downgrade the database.
|
||||
*/
|
||||
public final int version;
|
||||
|
||||
/**
|
||||
* Creates a new Callback to get database lifecycle events.
|
||||
*
|
||||
* @param version The version for the database instance. See {@link #version}.
|
||||
*/
|
||||
public Callback(int version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the database connection is being configured, to enable features such as
|
||||
* write-ahead logging or foreign key support.
|
||||
* <p>
|
||||
* This method is called before {@link #onCreate}, {@link #onUpgrade}, {@link #onDowngrade},
|
||||
* or {@link #onOpen} are called. It should not modify the database except to configure the
|
||||
* database connection as required.
|
||||
* </p>
|
||||
* <p>
|
||||
* This method should only call methods that configure the parameters of the database
|
||||
* connection, such as {@link SupportSQLiteDatabase#enableWriteAheadLogging}
|
||||
* {@link SupportSQLiteDatabase#setForeignKeyConstraintsEnabled},
|
||||
* {@link SupportSQLiteDatabase#setLocale},
|
||||
* {@link SupportSQLiteDatabase#setMaximumSize}, or executing PRAGMA statements.
|
||||
* </p>
|
||||
*
|
||||
* @param db The database.
|
||||
*/
|
||||
public void onConfigure(SupportSQLiteDatabase db) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the database is created for the first time. This is where the
|
||||
* creation of tables and the initial population of the tables should happen.
|
||||
*
|
||||
* @param db The database.
|
||||
*/
|
||||
public abstract void onCreate(SupportSQLiteDatabase db);
|
||||
|
||||
/**
|
||||
* Called when the database needs to be upgraded. The implementation
|
||||
* should use this method to drop tables, add tables, or do anything else it
|
||||
* needs to upgrade to the new schema version.
|
||||
*
|
||||
* <p>
|
||||
* The SQLite ALTER TABLE documentation can be found
|
||||
* <a href="http://sqlite.org/lang_altertable.html">here</a>. If you add new columns
|
||||
* you can use ALTER TABLE to insert them into a live table. If you rename or remove columns
|
||||
* you can use ALTER TABLE to rename the old table, then create the new table and then
|
||||
* populate the new table with the contents of the old table.
|
||||
* </p><p>
|
||||
* This method executes within a transaction. If an exception is thrown, all changes
|
||||
* will automatically be rolled back.
|
||||
* </p>
|
||||
*
|
||||
* @param db The database.
|
||||
* @param oldVersion The old database version.
|
||||
* @param newVersion The new database version.
|
||||
*/
|
||||
public abstract void onUpgrade(SupportSQLiteDatabase db, int oldVersion, int newVersion);
|
||||
|
||||
/**
|
||||
* Called when the database needs to be downgraded. This is strictly similar to
|
||||
* {@link #onUpgrade} method, but is called whenever current version is newer than requested
|
||||
* one.
|
||||
* However, this method is not abstract, so it is not mandatory for a customer to
|
||||
* implement it. If not overridden, default implementation will reject downgrade and
|
||||
* throws SQLiteException
|
||||
*
|
||||
* <p>
|
||||
* This method executes within a transaction. If an exception is thrown, all changes
|
||||
* will automatically be rolled back.
|
||||
* </p>
|
||||
*
|
||||
* @param db The database.
|
||||
* @param oldVersion The old database version.
|
||||
* @param newVersion The new database version.
|
||||
*/
|
||||
public void onDowngrade(SupportSQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
throw new SQLiteException("Can't downgrade database from version "
|
||||
+ oldVersion + " to " + newVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the database has been opened. The implementation
|
||||
* should check {@link SupportSQLiteDatabase#isReadOnly} before updating the
|
||||
* database.
|
||||
* <p>
|
||||
* This method is called after the database connection has been configured
|
||||
* and after the database schema has been created, upgraded or downgraded as necessary.
|
||||
* If the database connection must be configured in some way before the schema
|
||||
* is created, upgraded, or downgraded, do it in {@link #onConfigure} instead.
|
||||
* </p>
|
||||
*
|
||||
* @param db The database.
|
||||
*/
|
||||
public void onOpen(SupportSQLiteDatabase db) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The method invoked when database corruption is detected. Default implementation will
|
||||
* delete the database file.
|
||||
*
|
||||
* @param db the {@link SupportSQLiteDatabase} object representing the database on which
|
||||
* corruption is detected.
|
||||
*/
|
||||
public void onCorruption(SupportSQLiteDatabase db) {
|
||||
// the following implementation is taken from {@link DefaultDatabaseErrorHandler}.
|
||||
Log.e(TAG, "Corruption reported by sqlite on database: " + db.getPath());
|
||||
// is the corruption detected even before database could be 'opened'?
|
||||
if (!db.isOpen()) {
|
||||
// database files are not even openable. delete this database file.
|
||||
// NOTE if the database has attached databases, then any of them could be corrupt.
|
||||
// and not deleting all of them could cause corrupted database file to remain and
|
||||
// make the application crash on database open operation. To avoid this problem,
|
||||
// the application should provide its own {@link DatabaseErrorHandler} impl class
|
||||
// to delete ALL files of the database (including the attached databases).
|
||||
deleteDatabaseFile(db.getPath());
|
||||
return;
|
||||
}
|
||||
List<Pair<String, String>> attachedDbs = null;
|
||||
try {
|
||||
// Close the database, which will cause subsequent operations to fail.
|
||||
// before that, get the attached database list first.
|
||||
try {
|
||||
attachedDbs = db.getAttachedDbs();
|
||||
} catch (SQLiteException e) {
|
||||
/* ignore */
|
||||
}
|
||||
try {
|
||||
db.close();
|
||||
} catch (IOException e) {
|
||||
/* ignore */
|
||||
}
|
||||
} finally {
|
||||
// Delete all files of this corrupt database and/or attached databases
|
||||
if (attachedDbs != null) {
|
||||
for (Pair<String, String> p : attachedDbs) {
|
||||
deleteDatabaseFile(p.second);
|
||||
}
|
||||
} else {
|
||||
// attachedDbs = null is possible when the database is so corrupt that even
|
||||
// "PRAGMA database_list;" also fails. delete the main database file
|
||||
deleteDatabaseFile(db.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteDatabaseFile(String fileName) {
|
||||
if (fileName.equalsIgnoreCase(":memory:") || fileName.trim().length() == 0) {
|
||||
return;
|
||||
}
|
||||
Log.w(TAG, "deleting the database file: " + fileName);
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
SQLiteDatabase.deleteDatabase(new File(fileName));
|
||||
} else {
|
||||
try {
|
||||
final boolean deleted = new File(fileName).delete();
|
||||
if (!deleted) {
|
||||
Log.e(TAG, "Could not delete the database file " + fileName);
|
||||
}
|
||||
} catch (Exception error) {
|
||||
Log.e(TAG, "error while deleting corrupted database file", error);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
/* print warning and ignore exception */
|
||||
Log.w(TAG, "delete failed: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The configuration to create an SQLite open helper object using {@link Factory}.
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
class Configuration {
|
||||
/**
|
||||
* Context to use to open or create the database.
|
||||
*/
|
||||
@NonNull
|
||||
public final Context context;
|
||||
/**
|
||||
* Name of the database file, or null for an in-memory database.
|
||||
*/
|
||||
@Nullable
|
||||
public final String name;
|
||||
/**
|
||||
* The callback class to handle creation, upgrade and downgrade.
|
||||
*/
|
||||
@NonNull
|
||||
public final SupportSQLiteOpenHelper.Callback callback;
|
||||
|
||||
Configuration(@NonNull Context context, @Nullable String name, @NonNull Callback callback) {
|
||||
this.context = context;
|
||||
this.name = name;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Configuration.Builder to create an instance of Configuration.
|
||||
*
|
||||
* @param context to use to open or create the database.
|
||||
*/
|
||||
public static Builder builder(Context context) {
|
||||
return new Builder(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder class for {@link Configuration}.
|
||||
*/
|
||||
public static class Builder {
|
||||
Context mContext;
|
||||
String mName;
|
||||
SupportSQLiteOpenHelper.Callback mCallback;
|
||||
|
||||
Builder(@NonNull Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public Configuration build() {
|
||||
if (mCallback == null) {
|
||||
throw new IllegalArgumentException("Must set a callback to create the"
|
||||
+ " configuration.");
|
||||
}
|
||||
if (mContext == null) {
|
||||
throw new IllegalArgumentException("Must set a non-null context to create"
|
||||
+ " the configuration.");
|
||||
}
|
||||
return new Configuration(mContext, mName, mCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name Name of the database file, or null for an in-memory database.
|
||||
* @return This
|
||||
*/
|
||||
public Builder name(@Nullable String name) {
|
||||
mName = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callback The callback class to handle creation, upgrade and downgrade.
|
||||
* @return this
|
||||
*/
|
||||
public Builder callback(@NonNull Callback callback) {
|
||||
mCallback = callback;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.arch.persistence.db;
|
||||
|
||||
import java.io.Closeable;
|
||||
|
||||
/**
|
||||
* An interface to map the behavior of {@link android.database.sqlite.SQLiteProgram}.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface SupportSQLiteProgram extends Closeable {
|
||||
/**
|
||||
* Bind a NULL value to this statement. The value remains bound until
|
||||
* {@link #clearBindings} is called.
|
||||
*
|
||||
* @param index The 1-based index to the parameter to bind null to
|
||||
*/
|
||||
void bindNull(int index);
|
||||
|
||||
/**
|
||||
* Bind a long value to this statement. The value remains bound until
|
||||
* {@link #clearBindings} is called.
|
||||
* addToBindArgs
|
||||
*
|
||||
* @param index The 1-based index to the parameter to bind
|
||||
* @param value The value to bind
|
||||
*/
|
||||
void bindLong(int index, long value);
|
||||
|
||||
/**
|
||||
* Bind a double value to this statement. The value remains bound until
|
||||
* {@link #clearBindings} is called.
|
||||
*
|
||||
* @param index The 1-based index to the parameter to bind
|
||||
* @param value The value to bind
|
||||
*/
|
||||
void bindDouble(int index, double value);
|
||||
|
||||
/**
|
||||
* Bind a String value to this statement. The value remains bound until
|
||||
* {@link #clearBindings} is called.
|
||||
*
|
||||
* @param index The 1-based index to the parameter to bind
|
||||
* @param value The value to bind, must not be null
|
||||
*/
|
||||
void bindString(int index, String value);
|
||||
|
||||
/**
|
||||
* Bind a byte array value to this statement. The value remains bound until
|
||||
* {@link #clearBindings} is called.
|
||||
*
|
||||
* @param index The 1-based index to the parameter to bind
|
||||
* @param value The value to bind, must not be null
|
||||
*/
|
||||
void bindBlob(int index, byte[] value);
|
||||
|
||||
/**
|
||||
* Clears all existing bindings. Unset bindings are treated as NULL.
|
||||
*/
|
||||
void clearBindings();
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.arch.persistence.db;
|
||||
|
||||
/**
|
||||
* A query with typed bindings. It is better to use this API instead of
|
||||
* {@link android.database.sqlite.SQLiteDatabase#rawQuery(String, String[])} because it allows
|
||||
* binding type safe parameters.
|
||||
*/
|
||||
public interface SupportSQLiteQuery {
|
||||
/**
|
||||
* The SQL query. This query can have placeholders(?) for bind arguments.
|
||||
*
|
||||
* @return The SQL query to compile
|
||||
*/
|
||||
String getSql();
|
||||
|
||||
/**
|
||||
* Callback to bind the query parameters to the compiled statement.
|
||||
*
|
||||
* @param statement The compiled statement
|
||||
*/
|
||||
void bindTo(SupportSQLiteProgram statement);
|
||||
|
||||
/**
|
||||
* Returns the number of arguments in this query. This is equal to the number of placeholders
|
||||
* in the query string. See: https://www.sqlite.org/c3ref/bind_blob.html for details.
|
||||
*
|
||||
* @return The number of arguments in the query.
|
||||
*/
|
||||
int getArgCount();
|
||||
}
|
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.arch.persistence.db;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A simple query builder to create SQL SELECT queries.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public final class SupportSQLiteQueryBuilder {
|
||||
private static final Pattern sLimitPattern =
|
||||
Pattern.compile("\\s*\\d+\\s*(,\\s*\\d+\\s*)?");
|
||||
private final String mTable;
|
||||
private boolean mDistinct = false;
|
||||
private String[] mColumns = null;
|
||||
private String mSelection;
|
||||
private Object[] mBindArgs;
|
||||
private String mGroupBy = null;
|
||||
private String mHaving = null;
|
||||
private String mOrderBy = null;
|
||||
private String mLimit = null;
|
||||
|
||||
private SupportSQLiteQueryBuilder(String table) {
|
||||
mTable = table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a query for the given table name.
|
||||
*
|
||||
* @param tableName The table name(s) to query.
|
||||
* @return A builder to create a query.
|
||||
*/
|
||||
public static SupportSQLiteQueryBuilder builder(String tableName) {
|
||||
return new SupportSQLiteQueryBuilder(tableName);
|
||||
}
|
||||
|
||||
private static void appendClause(StringBuilder s, String name, String clause) {
|
||||
if (!isEmpty(clause)) {
|
||||
s.append(name);
|
||||
s.append(clause);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the names that are non-null in columns to s, separating
|
||||
* them with commas.
|
||||
*/
|
||||
private static void appendColumns(StringBuilder s, String[] columns) {
|
||||
int n = columns.length;
|
||||
for (int i = 0; i < n; i++) {
|
||||
String column = columns[i];
|
||||
if (i > 0) {
|
||||
s.append(", ");
|
||||
}
|
||||
s.append(column);
|
||||
}
|
||||
s.append(' ');
|
||||
}
|
||||
|
||||
private static boolean isEmpty(String input) {
|
||||
return input == null || input.length() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds DISTINCT keyword to the query.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
public SupportSQLiteQueryBuilder distinct() {
|
||||
mDistinct = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given list of columns as the columns that will be returned.
|
||||
*
|
||||
* @param columns The list of column names that should be returned.
|
||||
* @return this
|
||||
*/
|
||||
public SupportSQLiteQueryBuilder columns(String[] columns) {
|
||||
mColumns = columns;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the arguments for the WHERE clause.
|
||||
*
|
||||
* @param selection The list of selection columns
|
||||
* @param bindArgs The list of bind arguments to match against these columns
|
||||
* @return this
|
||||
*/
|
||||
public SupportSQLiteQueryBuilder selection(String selection, Object[] bindArgs) {
|
||||
mSelection = selection;
|
||||
mBindArgs = bindArgs;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a GROUP BY statement.
|
||||
*
|
||||
* @param groupBy The value of the GROUP BY statement.
|
||||
* @return this
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public SupportSQLiteQueryBuilder groupBy(String groupBy) {
|
||||
mGroupBy = groupBy;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a HAVING statement. You must also provide {@link #groupBy(String)} for this to work.
|
||||
*
|
||||
* @param having The having clause.
|
||||
* @return this
|
||||
*/
|
||||
public SupportSQLiteQueryBuilder having(String having) {
|
||||
mHaving = having;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an ORDER BY statement.
|
||||
*
|
||||
* @param orderBy The order clause.
|
||||
* @return this
|
||||
*/
|
||||
public SupportSQLiteQueryBuilder orderBy(String orderBy) {
|
||||
mOrderBy = orderBy;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a LIMIT statement.
|
||||
*
|
||||
* @param limit The limit value.
|
||||
* @return this
|
||||
*/
|
||||
public SupportSQLiteQueryBuilder limit(String limit) {
|
||||
if (!isEmpty(limit) && !sLimitPattern.matcher(limit).matches()) {
|
||||
throw new IllegalArgumentException("invalid LIMIT clauses:" + limit);
|
||||
}
|
||||
mLimit = limit;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the {@link SupportSQLiteQuery} that can be passed into
|
||||
* {@link SupportSQLiteDatabase#query(SupportSQLiteQuery)}.
|
||||
*
|
||||
* @return a new query
|
||||
*/
|
||||
public SupportSQLiteQuery create() {
|
||||
if (isEmpty(mGroupBy) && !isEmpty(mHaving)) {
|
||||
throw new IllegalArgumentException(
|
||||
"HAVING clauses are only permitted when using a groupBy clause");
|
||||
}
|
||||
StringBuilder query = new StringBuilder(120);
|
||||
query.append("SELECT ");
|
||||
if (mDistinct) {
|
||||
query.append("DISTINCT ");
|
||||
}
|
||||
if (mColumns != null && mColumns.length != 0) {
|
||||
appendColumns(query, mColumns);
|
||||
} else {
|
||||
query.append(" * ");
|
||||
}
|
||||
query.append(" FROM ");
|
||||
query.append(mTable);
|
||||
appendClause(query, " WHERE ", mSelection);
|
||||
appendClause(query, " GROUP BY ", mGroupBy);
|
||||
appendClause(query, " HAVING ", mHaving);
|
||||
appendClause(query, " ORDER BY ", mOrderBy);
|
||||
appendClause(query, " LIMIT ", mLimit);
|
||||
return new SimpleSQLiteQuery(query.toString(), mBindArgs);
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.arch.persistence.db;
|
||||
|
||||
/**
|
||||
* An interface to map the behavior of {@link android.database.sqlite.SQLiteStatement}.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface SupportSQLiteStatement extends SupportSQLiteProgram {
|
||||
/**
|
||||
* Execute this SQL statement, if it is not a SELECT / INSERT / DELETE / UPDATE, for example
|
||||
* CREATE / DROP table, view, trigger, index etc.
|
||||
*
|
||||
* @throws android.database.SQLException If the SQL string is invalid for
|
||||
* some reason
|
||||
*/
|
||||
void execute();
|
||||
|
||||
/**
|
||||
* Execute this SQL statement, if the the number of rows affected by execution of this SQL
|
||||
* statement is of any importance to the caller - for example, UPDATE / DELETE SQL statements.
|
||||
*
|
||||
* @return the number of rows affected by this SQL statement execution.
|
||||
* @throws android.database.SQLException If the SQL string is invalid for
|
||||
* some reason
|
||||
*/
|
||||
int executeUpdateDelete();
|
||||
|
||||
/**
|
||||
* Execute this SQL statement and return the ID of the row inserted due to this call.
|
||||
* The SQL statement should be an INSERT for this to be a useful call.
|
||||
*
|
||||
* @return the row ID of the last row inserted, if this insert is successful. -1 otherwise.
|
||||
* @throws android.database.SQLException If the SQL string is invalid for
|
||||
* some reason
|
||||
*/
|
||||
long executeInsert();
|
||||
|
||||
/**
|
||||
* Execute a statement that returns a 1 by 1 table with a numeric value.
|
||||
* For example, SELECT COUNT(*) FROM table;
|
||||
*
|
||||
* @return The result of the query.
|
||||
* @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
|
||||
*/
|
||||
long simpleQueryForLong();
|
||||
|
||||
/**
|
||||
* Execute a statement that returns a 1 by 1 table with a text value.
|
||||
* For example, SELECT COUNT(*) FROM table;
|
||||
*
|
||||
* @return The result of the query.
|
||||
* @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
|
||||
*/
|
||||
String simpleQueryForString();
|
||||
}
|
@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.arch.persistence.db.framework;
|
||||
|
||||
import android.arch.persistence.db.SimpleSQLiteQuery;
|
||||
import android.arch.persistence.db.SupportSQLiteDatabase;
|
||||
import android.arch.persistence.db.SupportSQLiteQuery;
|
||||
import android.arch.persistence.db.SupportSQLiteStatement;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.database.SQLException;
|
||||
import android.database.sqlite.*;
|
||||
import android.os.Build;
|
||||
import android.os.CancellationSignal;
|
||||
import android.util.Pair;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
|
||||
/**
|
||||
* Delegates all calls to an implementation of {@link SQLiteDatabase}.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
class FrameworkSQLiteDatabase implements SupportSQLiteDatabase {
|
||||
private static final String[] CONFLICT_VALUES = new String[]
|
||||
{"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "};
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
private final SQLiteDatabase mDelegate;
|
||||
|
||||
/**
|
||||
* Creates a wrapper around {@link SQLiteDatabase}.
|
||||
*
|
||||
* @param delegate The delegate to receive all calls.
|
||||
*/
|
||||
FrameworkSQLiteDatabase(SQLiteDatabase delegate) {
|
||||
mDelegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SupportSQLiteStatement compileStatement(String sql) {
|
||||
return new FrameworkSQLiteStatement(mDelegate.compileStatement(sql));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginTransaction() {
|
||||
mDelegate.beginTransaction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginTransactionNonExclusive() {
|
||||
mDelegate.beginTransactionNonExclusive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginTransactionWithListener(SQLiteTransactionListener transactionListener) {
|
||||
mDelegate.beginTransactionWithListener(transactionListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginTransactionWithListenerNonExclusive(
|
||||
SQLiteTransactionListener transactionListener) {
|
||||
mDelegate.beginTransactionWithListenerNonExclusive(transactionListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endTransaction() {
|
||||
mDelegate.endTransaction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransactionSuccessful() {
|
||||
mDelegate.setTransactionSuccessful();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean inTransaction() {
|
||||
return mDelegate.inTransaction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDbLockedByCurrentThread() {
|
||||
return mDelegate.isDbLockedByCurrentThread();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean yieldIfContendedSafely() {
|
||||
return mDelegate.yieldIfContendedSafely();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) {
|
||||
return mDelegate.yieldIfContendedSafely(sleepAfterYieldDelay);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVersion() {
|
||||
return mDelegate.getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVersion(int version) {
|
||||
mDelegate.setVersion(version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaximumSize() {
|
||||
return mDelegate.getMaximumSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long setMaximumSize(long numBytes) {
|
||||
return mDelegate.setMaximumSize(numBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getPageSize() {
|
||||
return mDelegate.getPageSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPageSize(long numBytes) {
|
||||
mDelegate.setPageSize(numBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(String query) {
|
||||
return query(new SimpleSQLiteQuery(query));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(String query, Object[] bindArgs) {
|
||||
return query(new SimpleSQLiteQuery(query, bindArgs));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(final SupportSQLiteQuery supportQuery) {
|
||||
return mDelegate.rawQueryWithFactory(new SQLiteDatabase.CursorFactory() {
|
||||
@Override
|
||||
public Cursor newCursor(SQLiteDatabase db, SQLiteCursorDriver masterQuery,
|
||||
String editTable, SQLiteQuery query) {
|
||||
supportQuery.bindTo(new FrameworkSQLiteProgram(query));
|
||||
return new SQLiteCursor(masterQuery, editTable, query);
|
||||
}
|
||||
}, supportQuery.getSql(), EMPTY_STRING_ARRAY, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@androidx.annotation.RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
|
||||
public Cursor query(final SupportSQLiteQuery supportQuery,
|
||||
CancellationSignal cancellationSignal) {
|
||||
return mDelegate.rawQueryWithFactory(new SQLiteDatabase.CursorFactory() {
|
||||
@Override
|
||||
public Cursor newCursor(SQLiteDatabase db, SQLiteCursorDriver masterQuery,
|
||||
String editTable, SQLiteQuery query) {
|
||||
supportQuery.bindTo(new FrameworkSQLiteProgram(query));
|
||||
return new SQLiteCursor(masterQuery, editTable, query);
|
||||
}
|
||||
}, supportQuery.getSql(), EMPTY_STRING_ARRAY, null, cancellationSignal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long insert(String table, int conflictAlgorithm, ContentValues values)
|
||||
throws SQLException {
|
||||
return mDelegate.insertWithOnConflict(table, null, values,
|
||||
conflictAlgorithm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(String table, String whereClause, Object[] whereArgs) {
|
||||
String query = "DELETE FROM " + table
|
||||
+ (isEmpty(whereClause) ? "" : " WHERE " + whereClause);
|
||||
SupportSQLiteStatement statement = compileStatement(query);
|
||||
SimpleSQLiteQuery.bind(statement, whereArgs);
|
||||
return statement.executeUpdateDelete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(String table, int conflictAlgorithm, ContentValues values, String whereClause,
|
||||
Object[] whereArgs) {
|
||||
// taken from SQLiteDatabase class.
|
||||
if (values == null || values.size() == 0) {
|
||||
throw new IllegalArgumentException("Empty values");
|
||||
}
|
||||
StringBuilder sql = new StringBuilder(120);
|
||||
sql.append("UPDATE ");
|
||||
sql.append(CONFLICT_VALUES[conflictAlgorithm]);
|
||||
sql.append(table);
|
||||
sql.append(" SET ");
|
||||
// move all bind args to one array
|
||||
int setValuesSize = values.size();
|
||||
int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length);
|
||||
Object[] bindArgs = new Object[bindArgsSize];
|
||||
int i = 0;
|
||||
for (String colName : values.keySet()) {
|
||||
sql.append((i > 0) ? "," : "");
|
||||
sql.append(colName);
|
||||
bindArgs[i++] = values.get(colName);
|
||||
sql.append("=?");
|
||||
}
|
||||
if (whereArgs != null) {
|
||||
for (i = setValuesSize; i < bindArgsSize; i++) {
|
||||
bindArgs[i] = whereArgs[i - setValuesSize];
|
||||
}
|
||||
}
|
||||
if (!isEmpty(whereClause)) {
|
||||
sql.append(" WHERE ");
|
||||
sql.append(whereClause);
|
||||
}
|
||||
SupportSQLiteStatement stmt = compileStatement(sql.toString());
|
||||
SimpleSQLiteQuery.bind(stmt, bindArgs);
|
||||
return stmt.executeUpdateDelete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execSQL(String sql) throws SQLException {
|
||||
mDelegate.execSQL(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execSQL(String sql, Object[] bindArgs) throws SQLException {
|
||||
mDelegate.execSQL(sql, bindArgs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return mDelegate.isReadOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpen() {
|
||||
return mDelegate.isOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needUpgrade(int newVersion) {
|
||||
return mDelegate.needUpgrade(newVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return mDelegate.getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocale(Locale locale) {
|
||||
mDelegate.setLocale(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxSqlCacheSize(int cacheSize) {
|
||||
mDelegate.setMaxSqlCacheSize(cacheSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
@androidx.annotation.RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
|
||||
public void setForeignKeyConstraintsEnabled(boolean enable) {
|
||||
mDelegate.setForeignKeyConstraintsEnabled(enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enableWriteAheadLogging() {
|
||||
return mDelegate.enableWriteAheadLogging();
|
||||
}
|
||||
|
||||
@Override
|
||||
@androidx.annotation.RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
|
||||
public void disableWriteAheadLogging() {
|
||||
mDelegate.disableWriteAheadLogging();
|
||||
}
|
||||
|
||||
@Override
|
||||
@androidx.annotation.RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
|
||||
public boolean isWriteAheadLoggingEnabled() {
|
||||
return mDelegate.isWriteAheadLoggingEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Pair<String, String>> getAttachedDbs() {
|
||||
return mDelegate.getAttachedDbs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDatabaseIntegrityOk() {
|
||||
return mDelegate.isDatabaseIntegrityOk();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
mDelegate.close();
|
||||
}
|
||||
}
|
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.arch.persistence.db.framework;
|
||||
|
||||
import android.arch.persistence.db.SupportSQLiteDatabase;
|
||||
import android.arch.persistence.db.SupportSQLiteOpenHelper;
|
||||
import android.content.Context;
|
||||
import android.database.DatabaseErrorHandler;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.os.Build;
|
||||
|
||||
class FrameworkSQLiteOpenHelper implements SupportSQLiteOpenHelper {
|
||||
private final OpenHelper mDelegate;
|
||||
|
||||
FrameworkSQLiteOpenHelper(Context context, String name,
|
||||
Callback callback) {
|
||||
mDelegate = createDelegate(context, name, callback);
|
||||
}
|
||||
|
||||
private OpenHelper createDelegate(Context context, String name, Callback callback) {
|
||||
final FrameworkSQLiteDatabase[] dbRef = new FrameworkSQLiteDatabase[1];
|
||||
return new OpenHelper(context, name, dbRef, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDatabaseName() {
|
||||
return mDelegate.getDatabaseName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@androidx.annotation.RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
|
||||
public void setWriteAheadLoggingEnabled(boolean enabled) {
|
||||
mDelegate.setWriteAheadLoggingEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SupportSQLiteDatabase getWritableDatabase() {
|
||||
return mDelegate.getWritableSupportDatabase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SupportSQLiteDatabase getReadableDatabase() {
|
||||
return mDelegate.getReadableSupportDatabase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
mDelegate.close();
|
||||
}
|
||||
|
||||
static class OpenHelper extends SQLiteOpenHelper {
|
||||
/**
|
||||
* This is used as an Object reference so that we can access the wrapped database inside
|
||||
* the constructor. SQLiteOpenHelper requires the error handler to be passed in the
|
||||
* constructor.
|
||||
*/
|
||||
final FrameworkSQLiteDatabase[] mDbRef;
|
||||
final Callback mCallback;
|
||||
// see b/78359448
|
||||
private boolean mMigrated;
|
||||
|
||||
OpenHelper(Context context, String name, final FrameworkSQLiteDatabase[] dbRef,
|
||||
final Callback callback) {
|
||||
super(context, name, null, callback.version,
|
||||
new DatabaseErrorHandler() {
|
||||
@Override
|
||||
public void onCorruption(SQLiteDatabase dbObj) {
|
||||
FrameworkSQLiteDatabase db = dbRef[0];
|
||||
if (db != null) {
|
||||
callback.onCorruption(db);
|
||||
}
|
||||
}
|
||||
});
|
||||
mCallback = callback;
|
||||
mDbRef = dbRef;
|
||||
}
|
||||
|
||||
synchronized SupportSQLiteDatabase getWritableSupportDatabase() {
|
||||
mMigrated = false;
|
||||
SQLiteDatabase db = super.getWritableDatabase();
|
||||
if (mMigrated) {
|
||||
// there might be a connection w/ stale structure, we should re-open.
|
||||
close();
|
||||
return getWritableSupportDatabase();
|
||||
}
|
||||
return getWrappedDb(db);
|
||||
}
|
||||
|
||||
synchronized SupportSQLiteDatabase getReadableSupportDatabase() {
|
||||
mMigrated = false;
|
||||
SQLiteDatabase db = super.getReadableDatabase();
|
||||
if (mMigrated) {
|
||||
// there might be a connection w/ stale structure, we should re-open.
|
||||
close();
|
||||
return getReadableSupportDatabase();
|
||||
}
|
||||
return getWrappedDb(db);
|
||||
}
|
||||
|
||||
FrameworkSQLiteDatabase getWrappedDb(SQLiteDatabase sqLiteDatabase) {
|
||||
FrameworkSQLiteDatabase dbRef = mDbRef[0];
|
||||
if (dbRef == null) {
|
||||
dbRef = new FrameworkSQLiteDatabase(sqLiteDatabase);
|
||||
mDbRef[0] = dbRef;
|
||||
}
|
||||
return mDbRef[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase sqLiteDatabase) {
|
||||
mCallback.onCreate(getWrappedDb(sqLiteDatabase));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
|
||||
mMigrated = true;
|
||||
mCallback.onUpgrade(getWrappedDb(sqLiteDatabase), oldVersion, newVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigure(SQLiteDatabase db) {
|
||||
mCallback.onConfigure(getWrappedDb(db));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
mMigrated = true;
|
||||
mCallback.onDowngrade(getWrappedDb(db), oldVersion, newVersion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(SQLiteDatabase db) {
|
||||
if (!mMigrated) {
|
||||
// if we've migrated, we'll re-open the db so we should not call the callback.
|
||||
mCallback.onOpen(getWrappedDb(db));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() {
|
||||
super.close();
|
||||
mDbRef[0] = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.arch.persistence.db.framework;
|
||||
|
||||
import android.arch.persistence.db.SupportSQLiteOpenHelper;
|
||||
|
||||
/**
|
||||
* Implements {@link SupportSQLiteOpenHelper.Factory} using the SQLite implementation in the
|
||||
* framework.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public final class FrameworkSQLiteOpenHelperFactory implements SupportSQLiteOpenHelper.Factory {
|
||||
@Override
|
||||
public SupportSQLiteOpenHelper create(SupportSQLiteOpenHelper.Configuration configuration) {
|
||||
return new FrameworkSQLiteOpenHelper(
|
||||
configuration.context, configuration.name, configuration.callback);
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.arch.persistence.db.framework;
|
||||
|
||||
import android.arch.persistence.db.SupportSQLiteProgram;
|
||||
import android.database.sqlite.SQLiteProgram;
|
||||
|
||||
/**
|
||||
* An wrapper around {@link SQLiteProgram} to implement {@link SupportSQLiteProgram} API.
|
||||
*/
|
||||
class FrameworkSQLiteProgram implements SupportSQLiteProgram {
|
||||
private final SQLiteProgram mDelegate;
|
||||
|
||||
FrameworkSQLiteProgram(SQLiteProgram delegate) {
|
||||
mDelegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindNull(int index) {
|
||||
mDelegate.bindNull(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindLong(int index, long value) {
|
||||
mDelegate.bindLong(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindDouble(int index, double value) {
|
||||
mDelegate.bindDouble(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindString(int index, String value) {
|
||||
mDelegate.bindString(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindBlob(int index, byte[] value) {
|
||||
mDelegate.bindBlob(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearBindings() {
|
||||
mDelegate.clearBindings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
mDelegate.close();
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.arch.persistence.db.framework;
|
||||
|
||||
import android.arch.persistence.db.SupportSQLiteStatement;
|
||||
import android.database.sqlite.SQLiteStatement;
|
||||
|
||||
/**
|
||||
* Delegates all calls to a {@link SQLiteStatement}.
|
||||
*/
|
||||
class FrameworkSQLiteStatement extends FrameworkSQLiteProgram implements SupportSQLiteStatement {
|
||||
private final SQLiteStatement mDelegate;
|
||||
|
||||
/**
|
||||
* Creates a wrapper around a framework {@link SQLiteStatement}.
|
||||
*
|
||||
* @param delegate The SQLiteStatement to delegate calls to.
|
||||
*/
|
||||
FrameworkSQLiteStatement(SQLiteStatement delegate) {
|
||||
super(delegate);
|
||||
mDelegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
mDelegate.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int executeUpdateDelete() {
|
||||
return mDelegate.executeUpdateDelete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long executeInsert() {
|
||||
return mDelegate.executeInsert();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long simpleQueryForLong() {
|
||||
return mDelegate.simpleQueryForLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String simpleQueryForString() {
|
||||
return mDelegate.simpleQueryForString();
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.content;
|
||||
import android.content.res.Configuration;
|
||||
/**
|
||||
* The set of callback APIs that are common to all application components
|
||||
* ({@link android.app.Activity}, {@link android.app.Service},
|
||||
* {@link ContentProvider}, and {@link android.app.Application}).
|
||||
*
|
||||
* <p class="note"><strong>Note:</strong> You should also implement the {@link
|
||||
* ComponentCallbacks2} interface, which provides the {@link
|
||||
* ComponentCallbacks2#onTrimMemory} callback to help your app manage its memory usage more
|
||||
* effectively.</p>
|
||||
*/
|
||||
public interface ComponentCallbacks {
|
||||
/**
|
||||
* Called by the system when the device configuration changes while your
|
||||
* component is running. Note that, unlike activities, other components
|
||||
* are never restarted when a configuration changes: they must always deal
|
||||
* with the results of the change, such as by re-retrieving resources.
|
||||
*
|
||||
* <p>At the time that this function has been called, your Resources
|
||||
* object will have been updated to return resource values matching the
|
||||
* new configuration.
|
||||
*
|
||||
* <p>For more information, read <a href="{@docRoot}guide/topics/resources/runtime-changes.html"
|
||||
* >Handling Runtime Changes</a>.
|
||||
*
|
||||
* @param newConfig The new device configuration.
|
||||
*/
|
||||
void onConfigurationChanged(Configuration newConfig);
|
||||
/**
|
||||
* This is called when the overall system is running low on memory, and
|
||||
* actively running processes should trim their memory usage. While
|
||||
* the exact point at which this will be called is not defined, generally
|
||||
* it will happen when all background process have been killed.
|
||||
* That is, before reaching the point of killing processes hosting
|
||||
* service and foreground UI that we would like to avoid killing.
|
||||
*
|
||||
* <p>You should implement this method to release
|
||||
* any caches or other unnecessary resources you may be holding on to.
|
||||
* The system will perform a garbage collection for you after returning from this method.
|
||||
* <p>Preferably, you should implement {@link ComponentCallbacks2#onTrimMemory} from
|
||||
* {@link ComponentCallbacks2} to incrementally unload your resources based on various
|
||||
* levels of memory demands. That API is available for API level 14 and higher, so you should
|
||||
* only use this {@link #onLowMemory} method as a fallback for older versions, which can be
|
||||
* treated the same as {@link ComponentCallbacks2#onTrimMemory} with the {@link
|
||||
* ComponentCallbacks2#TRIM_MEMORY_COMPLETE} level.</p>
|
||||
*/
|
||||
void onLowMemory();
|
||||
}
|
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.content;
|
||||
import android.annotation.IntDef;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
/**
|
||||
* Extended {@link ComponentCallbacks} interface with a new callback for
|
||||
* finer-grained memory management. This interface is available in all application components
|
||||
* ({@link android.app.Activity}, {@link android.app.Service},
|
||||
* {@link ContentProvider}, and {@link android.app.Application}).
|
||||
*
|
||||
* <p>You should implement {@link #onTrimMemory} to incrementally release memory based on current
|
||||
* system constraints. Using this callback to release your resources helps provide a more
|
||||
* responsive system overall, but also directly benefits the user experience for
|
||||
* your app by allowing the system to keep your process alive longer. That is,
|
||||
* if you <em>don't</em> trim your resources based on memory levels defined by this callback,
|
||||
* the system is more likely to kill your process while it is cached in the least-recently used
|
||||
* (LRU) list, thus requiring your app to restart and restore all state when the user returns to it.
|
||||
*
|
||||
* <p>The values provided by {@link #onTrimMemory} do not represent a single linear progression of
|
||||
* memory limits, but provide you different types of clues about memory availability:</p>
|
||||
* <ul>
|
||||
* <li>When your app is running:
|
||||
* <ol>
|
||||
* <li>{@link #TRIM_MEMORY_RUNNING_MODERATE} <br>The device is beginning to run low on memory.
|
||||
* Your app is running and not killable.
|
||||
* <li>{@link #TRIM_MEMORY_RUNNING_LOW} <br>The device is running much lower on memory.
|
||||
* Your app is running and not killable, but please release unused resources to improve system
|
||||
* performance (which directly impacts your app's performance).
|
||||
* <li>{@link #TRIM_MEMORY_RUNNING_CRITICAL} <br>The device is running extremely low on memory.
|
||||
* Your app is not yet considered a killable process, but the system will begin killing
|
||||
* background processes if apps do not release resources, so you should release non-critical
|
||||
* resources now to prevent performance degradation.
|
||||
* </ol>
|
||||
* </li>
|
||||
* <li>When your app's visibility changes:
|
||||
* <ol>
|
||||
* <li>{@link #TRIM_MEMORY_UI_HIDDEN} <br>Your app's UI is no longer visible, so this is a good
|
||||
* time to release large resources that are used only by your UI.
|
||||
* </ol>
|
||||
* </li>
|
||||
* <li>When your app's process resides in the background LRU list:
|
||||
* <ol>
|
||||
* <li>{@link #TRIM_MEMORY_BACKGROUND} <br>The system is running low on memory and your process is
|
||||
* near the beginning of the LRU list. Although your app process is not at a high risk of being
|
||||
* killed, the system may already be killing processes in the LRU list, so you should release
|
||||
* resources that are easy to recover so your process will remain in the list and resume
|
||||
* quickly when the user returns to your app.
|
||||
* <li>{@link #TRIM_MEMORY_MODERATE} <br>The system is running low on memory and your process is
|
||||
* near the middle of the LRU list. If the system becomes further constrained for memory, there's a
|
||||
* chance your process will be killed.
|
||||
* <li>{@link #TRIM_MEMORY_COMPLETE} <br>The system is running low on memory and your process is
|
||||
* one of the first to be killed if the system does not recover memory now. You should release
|
||||
* absolutely everything that's not critical to resuming your app state.
|
||||
* <p>To support API levels lower than 14, you can use the {@link #onLowMemory} method as a
|
||||
* fallback that's roughly equivalent to the {@link ComponentCallbacks2#TRIM_MEMORY_COMPLETE} level.
|
||||
* </li>
|
||||
* </ol>
|
||||
* <p class="note"><strong>Note:</strong> When the system begins
|
||||
* killing processes in the LRU list, although it primarily works bottom-up, it does give some
|
||||
* consideration to which processes are consuming more memory and will thus provide more gains in
|
||||
* memory if killed. So the less memory you consume while in the LRU list overall, the better
|
||||
* your chances are to remain in the list and be able to quickly resume.</p>
|
||||
* </li>
|
||||
* </ul>
|
||||
* <p>More information about the different stages of a process lifecycle (such as what it means
|
||||
* to be placed in the background LRU list) is provided in the <a
|
||||
* href="{@docRoot}guide/components/processes-and-threads.html#Lifecycle">Processes and Threads</a>
|
||||
* document.
|
||||
*/
|
||||
public interface ComponentCallbacks2 extends ComponentCallbacks {
|
||||
/** @hide */
|
||||
@IntDef(prefix = { "TRIM_MEMORY_" }, value = {
|
||||
TRIM_MEMORY_COMPLETE,
|
||||
TRIM_MEMORY_MODERATE,
|
||||
TRIM_MEMORY_BACKGROUND,
|
||||
TRIM_MEMORY_UI_HIDDEN,
|
||||
TRIM_MEMORY_RUNNING_CRITICAL,
|
||||
TRIM_MEMORY_RUNNING_LOW,
|
||||
TRIM_MEMORY_RUNNING_MODERATE,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface TrimMemoryLevel {}
|
||||
/**
|
||||
* Level for {@link #onTrimMemory(int)}: the process is nearing the end
|
||||
* of the background LRU list, and if more memory isn't found soon it will
|
||||
* be killed.
|
||||
*/
|
||||
static final int TRIM_MEMORY_COMPLETE = 80;
|
||||
|
||||
/**
|
||||
* Level for {@link #onTrimMemory(int)}: the process is around the middle
|
||||
* of the background LRU list; freeing memory can help the system keep
|
||||
* other processes running later in the list for better overall performance.
|
||||
*/
|
||||
static final int TRIM_MEMORY_MODERATE = 60;
|
||||
|
||||
/**
|
||||
* Level for {@link #onTrimMemory(int)}: the process has gone on to the
|
||||
* LRU list. This is a good opportunity to clean up resources that can
|
||||
* efficiently and quickly be re-built if the user returns to the app.
|
||||
*/
|
||||
static final int TRIM_MEMORY_BACKGROUND = 40;
|
||||
|
||||
/**
|
||||
* Level for {@link #onTrimMemory(int)}: the process had been showing
|
||||
* a user interface, and is no longer doing so. Large allocations with
|
||||
* the UI should be released at this point to allow memory to be better
|
||||
* managed.
|
||||
*/
|
||||
static final int TRIM_MEMORY_UI_HIDDEN = 20;
|
||||
/**
|
||||
* Level for {@link #onTrimMemory(int)}: the process is not an expendable
|
||||
* background process, but the device is running extremely low on memory
|
||||
* and is about to not be able to keep any background processes running.
|
||||
* Your running process should free up as many non-critical resources as it
|
||||
* can to allow that memory to be used elsewhere. The next thing that
|
||||
* will happen after this is {@link #onLowMemory()} called to report that
|
||||
* nothing at all can be kept in the background, a situation that can start
|
||||
* to notably impact the user.
|
||||
*/
|
||||
static final int TRIM_MEMORY_RUNNING_CRITICAL = 15;
|
||||
/**
|
||||
* Level for {@link #onTrimMemory(int)}: the process is not an expendable
|
||||
* background process, but the device is running low on memory.
|
||||
* Your running process should free up unneeded resources to allow that
|
||||
* memory to be used elsewhere.
|
||||
*/
|
||||
static final int TRIM_MEMORY_RUNNING_LOW = 10;
|
||||
/**
|
||||
* Level for {@link #onTrimMemory(int)}: the process is not an expendable
|
||||
* background process, but the device is running moderately low on memory.
|
||||
* Your running process may want to release some unneeded resources for
|
||||
* use elsewhere.
|
||||
*/
|
||||
static final int TRIM_MEMORY_RUNNING_MODERATE = 5;
|
||||
/**
|
||||
* Called when the operating system has determined that it is a good
|
||||
* time for a process to trim unneeded memory from its process. This will
|
||||
* happen for example when it goes in the background and there is not enough
|
||||
* memory to keep as many background processes running as desired. You
|
||||
* should never compare to exact values of the level, since new intermediate
|
||||
* values may be added -- you will typically want to compare if the value
|
||||
* is greater or equal to a level you are interested in.
|
||||
*
|
||||
* <p>To retrieve the processes current trim level at any point, you can
|
||||
* use {@link android.app.ActivityManager#getMyMemoryState
|
||||
* ActivityManager.getMyMemoryState(RunningAppProcessInfo)}.
|
||||
*
|
||||
* @param level The context of the trim, giving a hint of the amount of
|
||||
* trimming the application may like to perform.
|
||||
*/
|
||||
void onTrimMemory(@TrimMemoryLevel int level);
|
||||
}
|
362
AndroidCompat/src/main/java/android/content/ComponentName.java
Normal file
362
AndroidCompat/src/main/java/android/content/ComponentName.java
Normal file
@ -0,0 +1,362 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.content;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.Comparable;
|
||||
/**
|
||||
* Identifier for a specific application component
|
||||
* ({@link android.app.Activity}, {@link android.app.Service},
|
||||
* {@link android.content.BroadcastReceiver}, or
|
||||
* {@link android.content.ContentProvider}) that is available. Two
|
||||
* pieces of information, encapsulated here, are required to identify
|
||||
* a component: the package (a String) it exists in, and the class (a String)
|
||||
* name inside of that package.
|
||||
*
|
||||
*/
|
||||
public final class ComponentName implements Parcelable, Cloneable, Comparable<ComponentName> {
|
||||
private final String mPackage;
|
||||
private final String mClass;
|
||||
/**
|
||||
* Create a new component identifier where the class name may be specified
|
||||
* as either absolute or relative to the containing package.
|
||||
*
|
||||
* <p>Relative package names begin with a <code>'.'</code> character. For a package
|
||||
* <code>"com.example"</code> and class name <code>".app.MyActivity"</code> this method
|
||||
* will return a ComponentName with the package <code>"com.example"</code>and class name
|
||||
* <code>"com.example.app.MyActivity"</code>. Fully qualified class names are also
|
||||
* permitted.</p>
|
||||
*
|
||||
* @param pkg the name of the package the component exists in
|
||||
* @param cls the name of the class inside of <var>pkg</var> that implements
|
||||
* the component
|
||||
* @return the new ComponentName
|
||||
*/
|
||||
public static ComponentName createRelative(String pkg, String cls) {
|
||||
if (TextUtils.isEmpty(cls)) {
|
||||
throw new IllegalArgumentException("class name cannot be empty");
|
||||
}
|
||||
final String fullName;
|
||||
if (cls.charAt(0) == '.') {
|
||||
// Relative to the package. Prepend the package name.
|
||||
fullName = pkg + cls;
|
||||
} else {
|
||||
// Fully qualified package name.
|
||||
fullName = cls;
|
||||
}
|
||||
return new ComponentName(pkg, fullName);
|
||||
}
|
||||
/**
|
||||
* Create a new component identifier where the class name may be specified
|
||||
* as either absolute or relative to the containing package.
|
||||
*
|
||||
* <p>Relative package names begin with a <code>'.'</code> character. For a package
|
||||
* <code>"com.example"</code> and class name <code>".app.MyActivity"</code> this method
|
||||
* will return a ComponentName with the package <code>"com.example"</code>and class name
|
||||
* <code>"com.example.app.MyActivity"</code>. Fully qualified class names are also
|
||||
* permitted.</p>
|
||||
*
|
||||
* @param pkg a Context for the package implementing the component
|
||||
* @param cls the name of the class inside of <var>pkg</var> that implements
|
||||
* the component
|
||||
* @return the new ComponentName
|
||||
*/
|
||||
public static ComponentName createRelative(Context pkg, String cls) {
|
||||
return createRelative(pkg.getPackageName(), cls);
|
||||
}
|
||||
/**
|
||||
* Create a new component identifier.
|
||||
*
|
||||
* @param pkg The name of the package that the component exists in. Can
|
||||
* not be null.
|
||||
* @param cls The name of the class inside of <var>pkg</var> that
|
||||
* implements the component. Can not be null.
|
||||
*/
|
||||
public ComponentName(String pkg, String cls) {
|
||||
if (pkg == null) throw new NullPointerException("package name is null");
|
||||
if (cls == null) throw new NullPointerException("class name is null");
|
||||
mPackage = pkg;
|
||||
mClass = cls;
|
||||
}
|
||||
/**
|
||||
* Create a new component identifier from a Context and class name.
|
||||
*
|
||||
* @param pkg A Context for the package implementing the component,
|
||||
* from which the actual package name will be retrieved.
|
||||
* @param cls The name of the class inside of <var>pkg</var> that
|
||||
* implements the component.
|
||||
*/
|
||||
public ComponentName(Context pkg, String cls) {
|
||||
if (cls == null) throw new NullPointerException("class name is null");
|
||||
mPackage = pkg.getPackageName();
|
||||
mClass = cls;
|
||||
}
|
||||
/**
|
||||
* Create a new component identifier from a Context and Class object.
|
||||
*
|
||||
* @param pkg A Context for the package implementing the component, from
|
||||
* which the actual package name will be retrieved.
|
||||
* @param cls The Class object of the desired component, from which the
|
||||
* actual class name will be retrieved.
|
||||
*/
|
||||
public ComponentName(Context pkg, Class<?> cls) {
|
||||
mPackage = pkg.getPackageName();
|
||||
mClass = cls.getName();
|
||||
}
|
||||
public ComponentName clone() {
|
||||
return new ComponentName(mPackage, mClass);
|
||||
}
|
||||
/**
|
||||
* Return the package name of this component.
|
||||
*/
|
||||
public String getPackageName() {
|
||||
return mPackage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the class name of this component.
|
||||
*/
|
||||
public String getClassName() {
|
||||
return mClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the class name, either fully qualified or in a shortened form
|
||||
* (with a leading '.') if it is a suffix of the package.
|
||||
*/
|
||||
public String getShortClassName() {
|
||||
if (mClass.startsWith(mPackage)) {
|
||||
int PN = mPackage.length();
|
||||
int CN = mClass.length();
|
||||
if (CN > PN && mClass.charAt(PN) == '.') {
|
||||
return mClass.substring(PN, CN);
|
||||
}
|
||||
}
|
||||
return mClass;
|
||||
}
|
||||
|
||||
private static void appendShortClassName(StringBuilder sb, String packageName,
|
||||
String className) {
|
||||
if (className.startsWith(packageName)) {
|
||||
int PN = packageName.length();
|
||||
int CN = className.length();
|
||||
if (CN > PN && className.charAt(PN) == '.') {
|
||||
sb.append(className, PN, CN);
|
||||
return;
|
||||
}
|
||||
}
|
||||
sb.append(className);
|
||||
}
|
||||
private static void printShortClassName(PrintWriter pw, String packageName,
|
||||
String className) {
|
||||
if (className.startsWith(packageName)) {
|
||||
int PN = packageName.length();
|
||||
int CN = className.length();
|
||||
if (CN > PN && className.charAt(PN) == '.') {
|
||||
pw.write(className, PN, CN-PN);
|
||||
return;
|
||||
}
|
||||
}
|
||||
pw.print(className);
|
||||
}
|
||||
/**
|
||||
* Return a String that unambiguously describes both the package and
|
||||
* class names contained in the ComponentName. You can later recover
|
||||
* the ComponentName from this string through
|
||||
* {@link #unflattenFromString(String)}.
|
||||
*
|
||||
* @return Returns a new String holding the package and class names. This
|
||||
* is represented as the package name, concatenated with a '/' and then the
|
||||
* class name.
|
||||
*
|
||||
* @see #unflattenFromString(String)
|
||||
*/
|
||||
public String flattenToString() {
|
||||
return mPackage + "/" + mClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* The same as {@link #flattenToString()}, but abbreviates the class
|
||||
* name if it is a suffix of the package. The result can still be used
|
||||
* with {@link #unflattenFromString(String)}.
|
||||
*
|
||||
* @return Returns a new String holding the package and class names. This
|
||||
* is represented as the package name, concatenated with a '/' and then the
|
||||
* class name.
|
||||
*
|
||||
* @see #unflattenFromString(String)
|
||||
*/
|
||||
public String flattenToShortString() {
|
||||
StringBuilder sb = new StringBuilder(mPackage.length() + mClass.length());
|
||||
appendShortString(sb, mPackage, mClass);
|
||||
return sb.toString();
|
||||
}
|
||||
/** @hide */
|
||||
public void appendShortString(StringBuilder sb) {
|
||||
appendShortString(sb, mPackage, mClass);
|
||||
}
|
||||
/** @hide */
|
||||
public static void appendShortString(StringBuilder sb, String packageName, String className) {
|
||||
sb.append(packageName).append('/');
|
||||
appendShortClassName(sb, packageName, className);
|
||||
}
|
||||
/** @hide */
|
||||
public static void printShortString(PrintWriter pw, String packageName, String className) {
|
||||
pw.print(packageName);
|
||||
pw.print('/');
|
||||
printShortClassName(pw, packageName, className);
|
||||
}
|
||||
/**
|
||||
* Recover a ComponentName from a String that was previously created with
|
||||
* {@link #flattenToString()}. It splits the string at the first '/',
|
||||
* taking the part before as the package name and the part after as the
|
||||
* class name. As a special convenience (to use, for example, when
|
||||
* parsing component names on the command line), if the '/' is immediately
|
||||
* followed by a '.' then the final class name will be the concatenation
|
||||
* of the package name with the string following the '/'. Thus
|
||||
* "com.foo/.Blah" becomes package="com.foo" class="com.foo.Blah".
|
||||
*
|
||||
* @param str The String that was returned by flattenToString().
|
||||
* @return Returns a new ComponentName containing the package and class
|
||||
* names that were encoded in <var>str</var>
|
||||
*
|
||||
* @see #flattenToString()
|
||||
*/
|
||||
public static ComponentName unflattenFromString(String str) {
|
||||
int sep = str.indexOf('/');
|
||||
if (sep < 0 || (sep+1) >= str.length()) {
|
||||
return null;
|
||||
}
|
||||
String pkg = str.substring(0, sep);
|
||||
String cls = str.substring(sep+1);
|
||||
if (cls.length() > 0 && cls.charAt(0) == '.') {
|
||||
cls = pkg + cls;
|
||||
}
|
||||
return new ComponentName(pkg, cls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return string representation of this class without the class's name
|
||||
* as a prefix.
|
||||
*/
|
||||
public String toShortString() {
|
||||
return "{" + mPackage + "/" + mClass + "}";
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ComponentInfo{" + mPackage + "/" + mClass + "}";
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
try {
|
||||
if (obj != null) {
|
||||
ComponentName other = (ComponentName)obj;
|
||||
// Note: no null checks, because mPackage and mClass can
|
||||
// never be null.
|
||||
return mPackage.equals(other.mPackage)
|
||||
&& mClass.equals(other.mClass);
|
||||
}
|
||||
} catch (ClassCastException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mPackage.hashCode() + mClass.hashCode();
|
||||
}
|
||||
public int compareTo(ComponentName that) {
|
||||
int v;
|
||||
v = this.mPackage.compareTo(that.mPackage);
|
||||
if (v != 0) {
|
||||
return v;
|
||||
}
|
||||
return this.mClass.compareTo(that.mClass);
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(mPackage);
|
||||
out.writeString(mClass);
|
||||
}
|
||||
/**
|
||||
* Write a ComponentName to a Parcel, handling null pointers. Must be
|
||||
* read with {@link #readFromParcel(Parcel)}.
|
||||
*
|
||||
* @param c The ComponentName to be written.
|
||||
* @param out The Parcel in which the ComponentName will be placed.
|
||||
*
|
||||
* @see #readFromParcel(Parcel)
|
||||
*/
|
||||
public static void writeToParcel(ComponentName c, Parcel out) {
|
||||
if (c != null) {
|
||||
c.writeToParcel(out, 0);
|
||||
} else {
|
||||
out.writeString(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a ComponentName from a Parcel that was previously written
|
||||
* with {@link #writeToParcel(ComponentName, Parcel)}, returning either
|
||||
* a null or new object as appropriate.
|
||||
*
|
||||
* @param in The Parcel from which to read the ComponentName
|
||||
* @return Returns a new ComponentName matching the previously written
|
||||
* object, or null if a null had been written.
|
||||
*
|
||||
* @see #writeToParcel(ComponentName, Parcel)
|
||||
*/
|
||||
public static ComponentName readFromParcel(Parcel in) {
|
||||
String pkg = in.readString();
|
||||
return pkg != null ? new ComponentName(pkg, in) : null;
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<ComponentName> CREATOR
|
||||
= new Parcelable.Creator<ComponentName>() {
|
||||
public ComponentName createFromParcel(Parcel in) {
|
||||
return new ComponentName(in);
|
||||
}
|
||||
public ComponentName[] newArray(int size) {
|
||||
return new ComponentName[size];
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Instantiate a new ComponentName from the data in a Parcel that was
|
||||
* previously written with {@link #writeToParcel(Parcel, int)}. Note that you
|
||||
* must not use this with data written by
|
||||
* {@link #writeToParcel(ComponentName, Parcel)} since it is not possible
|
||||
* to handle a null ComponentObject here.
|
||||
*
|
||||
* @param in The Parcel containing the previously written ComponentName,
|
||||
* positioned at the location in the buffer where it was written.
|
||||
*/
|
||||
public ComponentName(Parcel in) {
|
||||
mPackage = in.readString();
|
||||
if (mPackage == null) throw new NullPointerException(
|
||||
"package name is null");
|
||||
mClass = in.readString();
|
||||
if (mClass == null) throw new NullPointerException(
|
||||
"class name is null");
|
||||
}
|
||||
private ComponentName(String pkg, Parcel in) {
|
||||
mPackage = pkg;
|
||||
mClass = in.readString();
|
||||
}
|
||||
}
|
473
AndroidCompat/src/main/java/android/content/ContentValues.java
Normal file
473
AndroidCompat/src/main/java/android/content/ContentValues.java
Normal file
@ -0,0 +1,473 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.content;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
/**
|
||||
* This class is used to store a set of values that the {@link ContentResolver}
|
||||
* can process.
|
||||
*/
|
||||
public final class ContentValues implements Parcelable {
|
||||
public static final String TAG = "ContentValues";
|
||||
/** Holds the actual values */
|
||||
private HashMap<String, Object> mValues;
|
||||
/**
|
||||
* Creates an empty set of values using the default initial size
|
||||
*/
|
||||
public ContentValues() {
|
||||
// Choosing a default size of 8 based on analysis of typical
|
||||
// consumption by applications.
|
||||
mValues = new HashMap<String, Object>(8);
|
||||
}
|
||||
/**
|
||||
* Creates an empty set of values using the given initial size
|
||||
*
|
||||
* @param size the initial size of the set of values
|
||||
*/
|
||||
public ContentValues(int size) {
|
||||
mValues = new HashMap<String, Object>(size, 1.0f);
|
||||
}
|
||||
/**
|
||||
* Creates a set of values copied from the given set
|
||||
*
|
||||
* @param from the values to copy
|
||||
*/
|
||||
public ContentValues(ContentValues from) {
|
||||
mValues = new HashMap<String, Object>(from.mValues);
|
||||
}
|
||||
/**
|
||||
* Creates a set of values copied from the given HashMap. This is used
|
||||
* by the Parcel unmarshalling code.
|
||||
*
|
||||
* @param values the values to start with
|
||||
* {@hide}
|
||||
*/
|
||||
private ContentValues(HashMap<String, Object> values) {
|
||||
mValues = values;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (!(object instanceof ContentValues)) {
|
||||
return false;
|
||||
}
|
||||
return mValues.equals(((ContentValues) object).mValues);
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mValues.hashCode();
|
||||
}
|
||||
/**
|
||||
* Adds a value to the set.
|
||||
*
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
public void put(String key, String value) {
|
||||
mValues.put(key, value);
|
||||
}
|
||||
/**
|
||||
* Adds all values from the passed in ContentValues.
|
||||
*
|
||||
* @param other the ContentValues from which to copy
|
||||
*/
|
||||
public void putAll(ContentValues other) {
|
||||
mValues.putAll(other.mValues);
|
||||
}
|
||||
/**
|
||||
* Adds a value to the set.
|
||||
*
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
public void put(String key, Byte value) {
|
||||
mValues.put(key, value);
|
||||
}
|
||||
/**
|
||||
* Adds a value to the set.
|
||||
*
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
public void put(String key, Short value) {
|
||||
mValues.put(key, value);
|
||||
}
|
||||
/**
|
||||
* Adds a value to the set.
|
||||
*
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
public void put(String key, Integer value) {
|
||||
mValues.put(key, value);
|
||||
}
|
||||
/**
|
||||
* Adds a value to the set.
|
||||
*
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
public void put(String key, Long value) {
|
||||
mValues.put(key, value);
|
||||
}
|
||||
/**
|
||||
* Adds a value to the set.
|
||||
*
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
public void put(String key, Float value) {
|
||||
mValues.put(key, value);
|
||||
}
|
||||
/**
|
||||
* Adds a value to the set.
|
||||
*
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
public void put(String key, Double value) {
|
||||
mValues.put(key, value);
|
||||
}
|
||||
/**
|
||||
* Adds a value to the set.
|
||||
*
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
public void put(String key, Boolean value) {
|
||||
mValues.put(key, value);
|
||||
}
|
||||
/**
|
||||
* Adds a value to the set.
|
||||
*
|
||||
* @param key the name of the value to put
|
||||
* @param value the data for the value to put
|
||||
*/
|
||||
public void put(String key, byte[] value) {
|
||||
mValues.put(key, value);
|
||||
}
|
||||
/**
|
||||
* Adds a null value to the set.
|
||||
*
|
||||
* @param key the name of the value to make null
|
||||
*/
|
||||
public void putNull(String key) {
|
||||
mValues.put(key, null);
|
||||
}
|
||||
/**
|
||||
* Returns the number of values.
|
||||
*
|
||||
* @return the number of values
|
||||
*/
|
||||
public int size() {
|
||||
return mValues.size();
|
||||
}
|
||||
/**
|
||||
* Remove a single value.
|
||||
*
|
||||
* @param key the name of the value to remove
|
||||
*/
|
||||
public void remove(String key) {
|
||||
mValues.remove(key);
|
||||
}
|
||||
/**
|
||||
* Removes all values.
|
||||
*/
|
||||
public void clear() {
|
||||
mValues.clear();
|
||||
}
|
||||
/**
|
||||
* Returns true if this object has the named value.
|
||||
*
|
||||
* @param key the value to check for
|
||||
* @return {@code true} if the value is present, {@code false} otherwise
|
||||
*/
|
||||
public boolean containsKey(String key) {
|
||||
return mValues.containsKey(key);
|
||||
}
|
||||
/**
|
||||
* Gets a value. Valid value types are {@link String}, {@link Boolean},
|
||||
* {@link Number}, and {@code byte[]} implementations.
|
||||
*
|
||||
* @param key the value to get
|
||||
* @return the data for the value, or {@code null} if the value is missing or if {@code null}
|
||||
* was previously added with the given {@code key}
|
||||
*/
|
||||
public Object get(String key) {
|
||||
return mValues.get(key);
|
||||
}
|
||||
/**
|
||||
* Gets a value and converts it to a String.
|
||||
*
|
||||
* @param key the value to get
|
||||
* @return the String for the value
|
||||
*/
|
||||
public String getAsString(String key) {
|
||||
Object value = mValues.get(key);
|
||||
return value != null ? value.toString() : null;
|
||||
}
|
||||
/**
|
||||
* Gets a value and converts it to a Long.
|
||||
*
|
||||
* @param key the value to get
|
||||
* @return the Long value, or {@code null} if the value is missing or cannot be converted
|
||||
*/
|
||||
public Long getAsLong(String key) {
|
||||
Object value = mValues.get(key);
|
||||
try {
|
||||
return value != null ? ((Number) value).longValue() : null;
|
||||
} catch (ClassCastException e) {
|
||||
if (value instanceof CharSequence) {
|
||||
try {
|
||||
return Long.valueOf(value.toString());
|
||||
} catch (NumberFormatException e2) {
|
||||
Log.e(TAG, "Cannot parse Long value for " + value + " at key " + key);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Cannot cast value for " + key + " to a Long: " + value, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Gets a value and converts it to an Integer.
|
||||
*
|
||||
* @param key the value to get
|
||||
* @return the Integer value, or {@code null} if the value is missing or cannot be converted
|
||||
*/
|
||||
public Integer getAsInteger(String key) {
|
||||
Object value = mValues.get(key);
|
||||
try {
|
||||
return value != null ? ((Number) value).intValue() : null;
|
||||
} catch (ClassCastException e) {
|
||||
if (value instanceof CharSequence) {
|
||||
try {
|
||||
return Integer.valueOf(value.toString());
|
||||
} catch (NumberFormatException e2) {
|
||||
Log.e(TAG, "Cannot parse Integer value for " + value + " at key " + key);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Cannot cast value for " + key + " to a Integer: " + value, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Gets a value and converts it to a Short.
|
||||
*
|
||||
* @param key the value to get
|
||||
* @return the Short value, or {@code null} if the value is missing or cannot be converted
|
||||
*/
|
||||
public Short getAsShort(String key) {
|
||||
Object value = mValues.get(key);
|
||||
try {
|
||||
return value != null ? ((Number) value).shortValue() : null;
|
||||
} catch (ClassCastException e) {
|
||||
if (value instanceof CharSequence) {
|
||||
try {
|
||||
return Short.valueOf(value.toString());
|
||||
} catch (NumberFormatException e2) {
|
||||
Log.e(TAG, "Cannot parse Short value for " + value + " at key " + key);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Cannot cast value for " + key + " to a Short: " + value, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Gets a value and converts it to a Byte.
|
||||
*
|
||||
* @param key the value to get
|
||||
* @return the Byte value, or {@code null} if the value is missing or cannot be converted
|
||||
*/
|
||||
public Byte getAsByte(String key) {
|
||||
Object value = mValues.get(key);
|
||||
try {
|
||||
return value != null ? ((Number) value).byteValue() : null;
|
||||
} catch (ClassCastException e) {
|
||||
if (value instanceof CharSequence) {
|
||||
try {
|
||||
return Byte.valueOf(value.toString());
|
||||
} catch (NumberFormatException e2) {
|
||||
Log.e(TAG, "Cannot parse Byte value for " + value + " at key " + key);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Cannot cast value for " + key + " to a Byte: " + value, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Gets a value and converts it to a Double.
|
||||
*
|
||||
* @param key the value to get
|
||||
* @return the Double value, or {@code null} if the value is missing or cannot be converted
|
||||
*/
|
||||
public Double getAsDouble(String key) {
|
||||
Object value = mValues.get(key);
|
||||
try {
|
||||
return value != null ? ((Number) value).doubleValue() : null;
|
||||
} catch (ClassCastException e) {
|
||||
if (value instanceof CharSequence) {
|
||||
try {
|
||||
return Double.valueOf(value.toString());
|
||||
} catch (NumberFormatException e2) {
|
||||
Log.e(TAG, "Cannot parse Double value for " + value + " at key " + key);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Cannot cast value for " + key + " to a Double: " + value, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Gets a value and converts it to a Float.
|
||||
*
|
||||
* @param key the value to get
|
||||
* @return the Float value, or {@code null} if the value is missing or cannot be converted
|
||||
*/
|
||||
public Float getAsFloat(String key) {
|
||||
Object value = mValues.get(key);
|
||||
try {
|
||||
return value != null ? ((Number) value).floatValue() : null;
|
||||
} catch (ClassCastException e) {
|
||||
if (value instanceof CharSequence) {
|
||||
try {
|
||||
return Float.valueOf(value.toString());
|
||||
} catch (NumberFormatException e2) {
|
||||
Log.e(TAG, "Cannot parse Float value for " + value + " at key " + key);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Cannot cast value for " + key + " to a Float: " + value, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Gets a value and converts it to a Boolean.
|
||||
*
|
||||
* @param key the value to get
|
||||
* @return the Boolean value, or {@code null} if the value is missing or cannot be converted
|
||||
*/
|
||||
public Boolean getAsBoolean(String key) {
|
||||
Object value = mValues.get(key);
|
||||
try {
|
||||
return (Boolean) value;
|
||||
} catch (ClassCastException e) {
|
||||
if (value instanceof CharSequence) {
|
||||
return Boolean.valueOf(value.toString());
|
||||
} else if (value instanceof Number) {
|
||||
return ((Number) value).intValue() != 0;
|
||||
} else {
|
||||
Log.e(TAG, "Cannot cast value for " + key + " to a Boolean: " + value, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Gets a value that is a byte array. Note that this method will not convert
|
||||
* any other types to byte arrays.
|
||||
*
|
||||
* @param key the value to get
|
||||
* @return the {@code byte[]} value, or {@code null} is the value is missing or not a
|
||||
* {@code byte[]}
|
||||
*/
|
||||
public byte[] getAsByteArray(String key) {
|
||||
Object value = mValues.get(key);
|
||||
if (value instanceof byte[]) {
|
||||
return (byte[]) value;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns a set of all of the keys and values
|
||||
*
|
||||
* @return a set of all of the keys and values
|
||||
*/
|
||||
public Set<Map.Entry<String, Object>> valueSet() {
|
||||
return mValues.entrySet();
|
||||
}
|
||||
/**
|
||||
* Returns a set of all of the keys
|
||||
*
|
||||
* @return a set of all of the keys
|
||||
*/
|
||||
public Set<String> keySet() {
|
||||
return mValues.keySet();
|
||||
}
|
||||
public static final Parcelable.Creator<ContentValues> CREATOR =
|
||||
new Parcelable.Creator<ContentValues>() {
|
||||
@SuppressWarnings({"deprecation", "unchecked"})
|
||||
public ContentValues createFromParcel(Parcel in) {
|
||||
// TODO - what ClassLoader should be passed to readHashMap?
|
||||
HashMap<String, Object> values = in.readHashMap(null);
|
||||
return new ContentValues(values);
|
||||
}
|
||||
public ContentValues[] newArray(int size) {
|
||||
return new ContentValues[size];
|
||||
}
|
||||
};
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
@SuppressWarnings("deprecation")
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeMap(mValues);
|
||||
}
|
||||
/**
|
||||
* Unsupported, here until we get proper bulk insert APIs.
|
||||
* {@hide}
|
||||
*/
|
||||
@Deprecated
|
||||
public void putStringArrayList(String key, ArrayList<String> value) {
|
||||
mValues.put(key, value);
|
||||
}
|
||||
/**
|
||||
* Unsupported, here until we get proper bulk insert APIs.
|
||||
* {@hide}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Deprecated
|
||||
public ArrayList<String> getStringArrayList(String key) {
|
||||
return (ArrayList<String>) mValues.get(key);
|
||||
}
|
||||
/**
|
||||
* Returns a string containing a concise, human-readable description of this object.
|
||||
* @return a printable representation of this object.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String name : mValues.keySet()) {
|
||||
String value = getAsString(name);
|
||||
if (sb.length() > 0) sb.append(" ");
|
||||
sb.append(name + "=" + value);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
4047
AndroidCompat/src/main/java/android/content/Context.java
Normal file
4047
AndroidCompat/src/main/java/android/content/Context.java
Normal file
File diff suppressed because it is too large
Load Diff
720
AndroidCompat/src/main/java/android/content/ContextWrapper.java
Normal file
720
AndroidCompat/src/main/java/android/content/ContextWrapper.java
Normal file
@ -0,0 +1,720 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.content;
|
||||
import android.annotation.SystemApi;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.AssetManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.database.DatabaseErrorHandler;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteDatabase.CursorFactory;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.UserHandle;
|
||||
import android.view.Display;
|
||||
import android.view.DisplayAdjustments;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
/**
|
||||
* Proxying implementation of Context that simply delegates all of its calls to
|
||||
* another Context. Can be subclassed to modify behavior without changing
|
||||
* the original Context.
|
||||
*/
|
||||
public class ContextWrapper extends Context {
|
||||
Context mBase;
|
||||
public ContextWrapper(Context base) {
|
||||
mBase = base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base context for this ContextWrapper. All calls will then be
|
||||
* delegated to the base context. Throws
|
||||
* IllegalStateException if a base context has already been set.
|
||||
*
|
||||
* @param base The new base context for this wrapper.
|
||||
*/
|
||||
protected void attachBaseContext(Context base) {
|
||||
if (mBase != null) {
|
||||
throw new IllegalStateException("Base context already set");
|
||||
}
|
||||
mBase = base;
|
||||
}
|
||||
/**
|
||||
* @return the base context as set by the constructor or setBaseContext
|
||||
*/
|
||||
public Context getBaseContext() {
|
||||
return mBase;
|
||||
}
|
||||
@Override
|
||||
public AssetManager getAssets() {
|
||||
return mBase.getAssets();
|
||||
}
|
||||
@Override
|
||||
public Resources getResources() {
|
||||
return mBase.getResources();
|
||||
}
|
||||
@Override
|
||||
public PackageManager getPackageManager() {
|
||||
return mBase.getPackageManager();
|
||||
}
|
||||
@Override
|
||||
public ContentResolver getContentResolver() {
|
||||
return mBase.getContentResolver();
|
||||
}
|
||||
@Override
|
||||
public Looper getMainLooper() {
|
||||
return mBase.getMainLooper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getApplicationContext() {
|
||||
return mBase.getApplicationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTheme(int resid) {
|
||||
mBase.setTheme(resid);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public int getThemeResId() {
|
||||
return mBase.getThemeResId();
|
||||
}
|
||||
@Override
|
||||
public Resources.Theme getTheme() {
|
||||
return mBase.getTheme();
|
||||
}
|
||||
@Override
|
||||
public ClassLoader getClassLoader() {
|
||||
return mBase.getClassLoader();
|
||||
}
|
||||
@Override
|
||||
public String getPackageName() {
|
||||
return mBase.getPackageName();
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public String getBasePackageName() {
|
||||
return mBase.getBasePackageName();
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public String getOpPackageName() {
|
||||
return mBase.getOpPackageName();
|
||||
}
|
||||
@Override
|
||||
public ApplicationInfo getApplicationInfo() {
|
||||
return mBase.getApplicationInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPackageResourcePath() {
|
||||
return mBase.getPackageResourcePath();
|
||||
}
|
||||
@Override
|
||||
public String getPackageCodePath() {
|
||||
return mBase.getPackageCodePath();
|
||||
}
|
||||
@Override
|
||||
public SharedPreferences getSharedPreferences(String name, int mode) {
|
||||
return mBase.getSharedPreferences(name, mode);
|
||||
}
|
||||
/** @removed */
|
||||
@Override
|
||||
public SharedPreferences getSharedPreferences(File file, int mode) {
|
||||
return mBase.getSharedPreferences(file, mode);
|
||||
}
|
||||
@Override
|
||||
public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
|
||||
return mBase.moveSharedPreferencesFrom(sourceContext, name);
|
||||
}
|
||||
@Override
|
||||
public boolean deleteSharedPreferences(String name) {
|
||||
return mBase.deleteSharedPreferences(name);
|
||||
}
|
||||
@Override
|
||||
public FileInputStream openFileInput(String name)
|
||||
throws FileNotFoundException {
|
||||
return mBase.openFileInput(name);
|
||||
}
|
||||
@Override
|
||||
public FileOutputStream openFileOutput(String name, int mode)
|
||||
throws FileNotFoundException {
|
||||
return mBase.openFileOutput(name, mode);
|
||||
}
|
||||
@Override
|
||||
public boolean deleteFile(String name) {
|
||||
return mBase.deleteFile(name);
|
||||
}
|
||||
@Override
|
||||
public File getFileStreamPath(String name) {
|
||||
return mBase.getFileStreamPath(name);
|
||||
}
|
||||
/** @removed */
|
||||
@Override
|
||||
public File getSharedPreferencesPath(String name) {
|
||||
return mBase.getSharedPreferencesPath(name);
|
||||
}
|
||||
@Override
|
||||
public String[] fileList() {
|
||||
return mBase.fileList();
|
||||
}
|
||||
@Override
|
||||
public File getDataDir() {
|
||||
return mBase.getDataDir();
|
||||
}
|
||||
@Override
|
||||
public File getFilesDir() {
|
||||
return mBase.getFilesDir();
|
||||
}
|
||||
@Override
|
||||
public File getNoBackupFilesDir() {
|
||||
return mBase.getNoBackupFilesDir();
|
||||
}
|
||||
@Override
|
||||
public File getExternalFilesDir(String type) {
|
||||
return mBase.getExternalFilesDir(type);
|
||||
}
|
||||
@Override
|
||||
public File[] getExternalFilesDirs(String type) {
|
||||
return mBase.getExternalFilesDirs(type);
|
||||
}
|
||||
@Override
|
||||
public File getObbDir() {
|
||||
return mBase.getObbDir();
|
||||
}
|
||||
@Override
|
||||
public File[] getObbDirs() {
|
||||
return mBase.getObbDirs();
|
||||
}
|
||||
@Override
|
||||
public File getCacheDir() {
|
||||
return mBase.getCacheDir();
|
||||
}
|
||||
@Override
|
||||
public File getCodeCacheDir() {
|
||||
return mBase.getCodeCacheDir();
|
||||
}
|
||||
@Override
|
||||
public File getExternalCacheDir() {
|
||||
return mBase.getExternalCacheDir();
|
||||
}
|
||||
@Override
|
||||
public File[] getExternalCacheDirs() {
|
||||
return mBase.getExternalCacheDirs();
|
||||
}
|
||||
@Override
|
||||
public File[] getExternalMediaDirs() {
|
||||
return mBase.getExternalMediaDirs();
|
||||
}
|
||||
@Override
|
||||
public File getDir(String name, int mode) {
|
||||
return mBase.getDir(name, mode);
|
||||
}
|
||||
@Override
|
||||
public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
|
||||
return mBase.openOrCreateDatabase(name, mode, factory);
|
||||
}
|
||||
@Override
|
||||
public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
|
||||
DatabaseErrorHandler errorHandler) {
|
||||
return mBase.openOrCreateDatabase(name, mode, factory, errorHandler);
|
||||
}
|
||||
@Override
|
||||
public boolean moveDatabaseFrom(Context sourceContext, String name) {
|
||||
return mBase.moveDatabaseFrom(sourceContext, name);
|
||||
}
|
||||
@Override
|
||||
public boolean deleteDatabase(String name) {
|
||||
return mBase.deleteDatabase(name);
|
||||
}
|
||||
@Override
|
||||
public File getDatabasePath(String name) {
|
||||
return mBase.getDatabasePath(name);
|
||||
}
|
||||
@Override
|
||||
public String[] databaseList() {
|
||||
return mBase.databaseList();
|
||||
}
|
||||
@Override
|
||||
@Deprecated
|
||||
public Drawable getWallpaper() {
|
||||
return mBase.getWallpaper();
|
||||
}
|
||||
@Override
|
||||
@Deprecated
|
||||
public Drawable peekWallpaper() {
|
||||
return mBase.peekWallpaper();
|
||||
}
|
||||
@Override
|
||||
@Deprecated
|
||||
public int getWallpaperDesiredMinimumWidth() {
|
||||
return mBase.getWallpaperDesiredMinimumWidth();
|
||||
}
|
||||
@Override
|
||||
@Deprecated
|
||||
public int getWallpaperDesiredMinimumHeight() {
|
||||
return mBase.getWallpaperDesiredMinimumHeight();
|
||||
}
|
||||
@Override
|
||||
@Deprecated
|
||||
public void setWallpaper(Bitmap bitmap) throws IOException {
|
||||
mBase.setWallpaper(bitmap);
|
||||
}
|
||||
@Override
|
||||
@Deprecated
|
||||
public void setWallpaper(InputStream data) throws IOException {
|
||||
mBase.setWallpaper(data);
|
||||
}
|
||||
@Override
|
||||
@Deprecated
|
||||
public void clearWallpaper() throws IOException {
|
||||
mBase.clearWallpaper();
|
||||
}
|
||||
@Override
|
||||
public void startActivity(Intent intent) {
|
||||
mBase.startActivity(intent);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public void startActivityAsUser(Intent intent, UserHandle user) {
|
||||
mBase.startActivityAsUser(intent, user);
|
||||
}
|
||||
/** @hide **/
|
||||
public void startActivityForResult(
|
||||
String who, Intent intent, int requestCode, Bundle options) {
|
||||
mBase.startActivityForResult(who, intent, requestCode, options);
|
||||
}
|
||||
/** @hide **/
|
||||
public boolean canStartActivityForResult() {
|
||||
return mBase.canStartActivityForResult();
|
||||
}
|
||||
@Override
|
||||
public void startActivity(Intent intent, Bundle options) {
|
||||
mBase.startActivity(intent, options);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) {
|
||||
mBase.startActivityAsUser(intent, options, user);
|
||||
}
|
||||
@Override
|
||||
public void startActivities(Intent[] intents) {
|
||||
mBase.startActivities(intents);
|
||||
}
|
||||
@Override
|
||||
public void startActivities(Intent[] intents, Bundle options) {
|
||||
mBase.startActivities(intents, options);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public void startActivitiesAsUser(Intent[] intents, Bundle options, UserHandle userHandle) {
|
||||
mBase.startActivitiesAsUser(intents, options, userHandle);
|
||||
}
|
||||
@Override
|
||||
public void startIntentSender(IntentSender intent,
|
||||
Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
|
||||
throws IntentSender.SendIntentException {
|
||||
mBase.startIntentSender(intent, fillInIntent, flagsMask,
|
||||
flagsValues, extraFlags);
|
||||
}
|
||||
@Override
|
||||
public void startIntentSender(IntentSender intent,
|
||||
Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
|
||||
Bundle options) throws IntentSender.SendIntentException {
|
||||
mBase.startIntentSender(intent, fillInIntent, flagsMask,
|
||||
flagsValues, extraFlags, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBroadcast(Intent intent) {
|
||||
mBase.sendBroadcast(intent);
|
||||
}
|
||||
@Override
|
||||
public void sendBroadcast(Intent intent, String receiverPermission) {
|
||||
mBase.sendBroadcast(intent, receiverPermission);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) {
|
||||
mBase.sendBroadcastMultiplePermissions(intent, receiverPermissions);
|
||||
}
|
||||
/** @hide */
|
||||
@SystemApi
|
||||
@Override
|
||||
public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
|
||||
mBase.sendBroadcast(intent, receiverPermission, options);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
|
||||
mBase.sendBroadcast(intent, receiverPermission, appOp);
|
||||
}
|
||||
@Override
|
||||
public void sendOrderedBroadcast(Intent intent,
|
||||
String receiverPermission) {
|
||||
mBase.sendOrderedBroadcast(intent, receiverPermission);
|
||||
}
|
||||
@Override
|
||||
public void sendOrderedBroadcast(
|
||||
Intent intent, String receiverPermission, BroadcastReceiver resultReceiver,
|
||||
Handler scheduler, int initialCode, String initialData,
|
||||
Bundle initialExtras) {
|
||||
mBase.sendOrderedBroadcast(intent, receiverPermission,
|
||||
resultReceiver, scheduler, initialCode,
|
||||
initialData, initialExtras);
|
||||
}
|
||||
/** @hide */
|
||||
@SystemApi
|
||||
@Override
|
||||
public void sendOrderedBroadcast(
|
||||
Intent intent, String receiverPermission, Bundle options, BroadcastReceiver resultReceiver,
|
||||
Handler scheduler, int initialCode, String initialData,
|
||||
Bundle initialExtras) {
|
||||
mBase.sendOrderedBroadcast(intent, receiverPermission,
|
||||
options, resultReceiver, scheduler, initialCode,
|
||||
initialData, initialExtras);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public void sendOrderedBroadcast(
|
||||
Intent intent, String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
|
||||
Handler scheduler, int initialCode, String initialData,
|
||||
Bundle initialExtras) {
|
||||
mBase.sendOrderedBroadcast(intent, receiverPermission, appOp,
|
||||
resultReceiver, scheduler, initialCode,
|
||||
initialData, initialExtras);
|
||||
}
|
||||
@Override
|
||||
public void sendBroadcastAsUser(Intent intent, UserHandle user) {
|
||||
mBase.sendBroadcastAsUser(intent, user);
|
||||
}
|
||||
@Override
|
||||
public void sendBroadcastAsUser(Intent intent, UserHandle user,
|
||||
String receiverPermission) {
|
||||
mBase.sendBroadcastAsUser(intent, user, receiverPermission);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public void sendBroadcastAsUser(Intent intent, UserHandle user,
|
||||
String receiverPermission, int appOp) {
|
||||
mBase.sendBroadcastAsUser(intent, user, receiverPermission, appOp);
|
||||
}
|
||||
@Override
|
||||
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
|
||||
String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
|
||||
int initialCode, String initialData, Bundle initialExtras) {
|
||||
mBase.sendOrderedBroadcastAsUser(intent, user, receiverPermission, resultReceiver,
|
||||
scheduler, initialCode, initialData, initialExtras);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
|
||||
String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
|
||||
Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
|
||||
mBase.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp, resultReceiver,
|
||||
scheduler, initialCode, initialData, initialExtras);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
|
||||
String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver,
|
||||
Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
|
||||
mBase.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp, options,
|
||||
resultReceiver, scheduler, initialCode, initialData, initialExtras);
|
||||
}
|
||||
@Override
|
||||
@Deprecated
|
||||
public void sendStickyBroadcast(Intent intent) {
|
||||
mBase.sendStickyBroadcast(intent);
|
||||
}
|
||||
@Override
|
||||
@Deprecated
|
||||
public void sendStickyOrderedBroadcast(
|
||||
Intent intent, BroadcastReceiver resultReceiver,
|
||||
Handler scheduler, int initialCode, String initialData,
|
||||
Bundle initialExtras) {
|
||||
mBase.sendStickyOrderedBroadcast(intent,
|
||||
resultReceiver, scheduler, initialCode,
|
||||
initialData, initialExtras);
|
||||
}
|
||||
@Override
|
||||
@Deprecated
|
||||
public void removeStickyBroadcast(Intent intent) {
|
||||
mBase.removeStickyBroadcast(intent);
|
||||
}
|
||||
@Override
|
||||
@Deprecated
|
||||
public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
|
||||
mBase.sendStickyBroadcastAsUser(intent, user);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
@Deprecated
|
||||
public void sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options) {
|
||||
mBase.sendStickyBroadcastAsUser(intent, user, options);
|
||||
}
|
||||
@Override
|
||||
@Deprecated
|
||||
public void sendStickyOrderedBroadcastAsUser(Intent intent,
|
||||
UserHandle user, BroadcastReceiver resultReceiver,
|
||||
Handler scheduler, int initialCode, String initialData,
|
||||
Bundle initialExtras) {
|
||||
mBase.sendStickyOrderedBroadcastAsUser(intent, user, resultReceiver,
|
||||
scheduler, initialCode, initialData, initialExtras);
|
||||
}
|
||||
@Override
|
||||
@Deprecated
|
||||
public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
|
||||
mBase.removeStickyBroadcastAsUser(intent, user);
|
||||
}
|
||||
@Override
|
||||
public Intent registerReceiver(
|
||||
BroadcastReceiver receiver, IntentFilter filter) {
|
||||
return mBase.registerReceiver(receiver, filter);
|
||||
}
|
||||
@Override
|
||||
public Intent registerReceiver(
|
||||
BroadcastReceiver receiver, IntentFilter filter,
|
||||
String broadcastPermission, Handler scheduler) {
|
||||
return mBase.registerReceiver(receiver, filter, broadcastPermission,
|
||||
scheduler);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public Intent registerReceiverAsUser(
|
||||
BroadcastReceiver receiver, UserHandle user, IntentFilter filter,
|
||||
String broadcastPermission, Handler scheduler) {
|
||||
return mBase.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
|
||||
scheduler);
|
||||
}
|
||||
@Override
|
||||
public void unregisterReceiver(BroadcastReceiver receiver) {
|
||||
mBase.unregisterReceiver(receiver);
|
||||
}
|
||||
@Override
|
||||
public ComponentName startService(Intent service) {
|
||||
return mBase.startService(service);
|
||||
}
|
||||
@Override
|
||||
public boolean stopService(Intent name) {
|
||||
return mBase.stopService(name);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public ComponentName startServiceAsUser(Intent service, UserHandle user) {
|
||||
return mBase.startServiceAsUser(service, user);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public boolean stopServiceAsUser(Intent name, UserHandle user) {
|
||||
return mBase.stopServiceAsUser(name, user);
|
||||
}
|
||||
@Override
|
||||
public boolean bindService(Intent service, ServiceConnection conn,
|
||||
int flags) {
|
||||
return mBase.bindService(service, conn, flags);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
|
||||
UserHandle user) {
|
||||
return mBase.bindServiceAsUser(service, conn, flags, user);
|
||||
}
|
||||
@Override
|
||||
public void unbindService(ServiceConnection conn) {
|
||||
mBase.unbindService(conn);
|
||||
}
|
||||
@Override
|
||||
public boolean startInstrumentation(ComponentName className,
|
||||
String profileFile, Bundle arguments) {
|
||||
return mBase.startInstrumentation(className, profileFile, arguments);
|
||||
}
|
||||
@Override
|
||||
public Object getSystemService(String name) {
|
||||
return mBase.getSystemService(name);
|
||||
}
|
||||
@Override
|
||||
public String getSystemServiceName(Class<?> serviceClass) {
|
||||
return mBase.getSystemServiceName(serviceClass);
|
||||
}
|
||||
@Override
|
||||
public int checkPermission(String permission, int pid, int uid) {
|
||||
return mBase.checkPermission(permission, pid, uid);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public int checkPermission(String permission, int pid, int uid, IBinder callerToken) {
|
||||
return mBase.checkPermission(permission, pid, uid, callerToken);
|
||||
}
|
||||
@Override
|
||||
public int checkCallingPermission(String permission) {
|
||||
return mBase.checkCallingPermission(permission);
|
||||
}
|
||||
@Override
|
||||
public int checkCallingOrSelfPermission(String permission) {
|
||||
return mBase.checkCallingOrSelfPermission(permission);
|
||||
}
|
||||
@Override
|
||||
public int checkSelfPermission(String permission) {
|
||||
return mBase.checkSelfPermission(permission);
|
||||
}
|
||||
@Override
|
||||
public void enforcePermission(
|
||||
String permission, int pid, int uid, String message) {
|
||||
mBase.enforcePermission(permission, pid, uid, message);
|
||||
}
|
||||
@Override
|
||||
public void enforceCallingPermission(String permission, String message) {
|
||||
mBase.enforceCallingPermission(permission, message);
|
||||
}
|
||||
@Override
|
||||
public void enforceCallingOrSelfPermission(
|
||||
String permission, String message) {
|
||||
mBase.enforceCallingOrSelfPermission(permission, message);
|
||||
}
|
||||
@Override
|
||||
public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
|
||||
mBase.grantUriPermission(toPackage, uri, modeFlags);
|
||||
}
|
||||
@Override
|
||||
public void revokeUriPermission(Uri uri, int modeFlags) {
|
||||
mBase.revokeUriPermission(uri, modeFlags);
|
||||
}
|
||||
@Override
|
||||
public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
|
||||
return mBase.checkUriPermission(uri, pid, uid, modeFlags);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags, IBinder callerToken) {
|
||||
return mBase.checkUriPermission(uri, pid, uid, modeFlags, callerToken);
|
||||
}
|
||||
@Override
|
||||
public int checkCallingUriPermission(Uri uri, int modeFlags) {
|
||||
return mBase.checkCallingUriPermission(uri, modeFlags);
|
||||
}
|
||||
@Override
|
||||
public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
|
||||
return mBase.checkCallingOrSelfUriPermission(uri, modeFlags);
|
||||
}
|
||||
@Override
|
||||
public int checkUriPermission(Uri uri, String readPermission,
|
||||
String writePermission, int pid, int uid, int modeFlags) {
|
||||
return mBase.checkUriPermission(uri, readPermission, writePermission,
|
||||
pid, uid, modeFlags);
|
||||
}
|
||||
@Override
|
||||
public void enforceUriPermission(
|
||||
Uri uri, int pid, int uid, int modeFlags, String message) {
|
||||
mBase.enforceUriPermission(uri, pid, uid, modeFlags, message);
|
||||
}
|
||||
@Override
|
||||
public void enforceCallingUriPermission(
|
||||
Uri uri, int modeFlags, String message) {
|
||||
mBase.enforceCallingUriPermission(uri, modeFlags, message);
|
||||
}
|
||||
@Override
|
||||
public void enforceCallingOrSelfUriPermission(
|
||||
Uri uri, int modeFlags, String message) {
|
||||
mBase.enforceCallingOrSelfUriPermission(uri, modeFlags, message);
|
||||
}
|
||||
@Override
|
||||
public void enforceUriPermission(
|
||||
Uri uri, String readPermission, String writePermission,
|
||||
int pid, int uid, int modeFlags, String message) {
|
||||
mBase.enforceUriPermission(
|
||||
uri, readPermission, writePermission, pid, uid, modeFlags,
|
||||
message);
|
||||
}
|
||||
@Override
|
||||
public Context createPackageContext(String packageName, int flags)
|
||||
throws PackageManager.NameNotFoundException {
|
||||
return mBase.createPackageContext(packageName, flags);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
|
||||
throws PackageManager.NameNotFoundException {
|
||||
return mBase.createPackageContextAsUser(packageName, flags, user);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public Context createApplicationContext(ApplicationInfo application,
|
||||
int flags) throws PackageManager.NameNotFoundException {
|
||||
return mBase.createApplicationContext(application, flags);
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public int getUserId() {
|
||||
return mBase.getUserId();
|
||||
}
|
||||
@Override
|
||||
public Context createConfigurationContext(Configuration overrideConfiguration) {
|
||||
return mBase.createConfigurationContext(overrideConfiguration);
|
||||
}
|
||||
@Override
|
||||
public Context createDisplayContext(Display display) {
|
||||
return mBase.createDisplayContext(display);
|
||||
}
|
||||
@Override
|
||||
public boolean isRestricted() {
|
||||
return mBase.isRestricted();
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public DisplayAdjustments getDisplayAdjustments(int displayId) {
|
||||
return mBase.getDisplayAdjustments(displayId);
|
||||
}
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@Override
|
||||
public Display getDisplay() {
|
||||
return mBase.getDisplay();
|
||||
}
|
||||
@Override
|
||||
public Context createDeviceProtectedStorageContext() {
|
||||
return mBase.createDeviceProtectedStorageContext();
|
||||
}
|
||||
/** {@hide} */
|
||||
@SystemApi
|
||||
@Override
|
||||
public Context createCredentialProtectedStorageContext() {
|
||||
return mBase.createCredentialProtectedStorageContext();
|
||||
}
|
||||
@Override
|
||||
public boolean isDeviceProtectedStorage() {
|
||||
return mBase.isDeviceProtectedStorage();
|
||||
}
|
||||
/** {@hide} */
|
||||
@SystemApi
|
||||
@Override
|
||||
public boolean isCredentialProtectedStorage() {
|
||||
return mBase.isCredentialProtectedStorage();
|
||||
}
|
||||
}
|
7625
AndroidCompat/src/main/java/android/content/Intent.java
Normal file
7625
AndroidCompat/src/main/java/android/content/Intent.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,370 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.content;
|
||||
import android.annotation.Nullable;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
/**
|
||||
* Interface for accessing and modifying preference data returned by {@link
|
||||
* Context#getSharedPreferences}. For any particular set of preferences,
|
||||
* there is a single instance of this class that all clients share.
|
||||
* Modifications to the preferences must go through an {@link Editor} object
|
||||
* to ensure the preference values remain in a consistent state and control
|
||||
* when they are committed to storage. Objects that are returned from the
|
||||
* various <code>get</code> methods must be treated as immutable by the application.
|
||||
*
|
||||
* <p><em>Note: This class does not support use across multiple processes.</em>
|
||||
*
|
||||
* <div class="special reference">
|
||||
* <h3>Developer Guides</h3>
|
||||
* <p>For more information about using SharedPreferences, read the
|
||||
* <a href="{@docRoot}guide/topics/data/data-storage.html#pref">Data Storage</a>
|
||||
* developer guide.</p></div>
|
||||
*
|
||||
* @see Context#getSharedPreferences
|
||||
*/
|
||||
public interface SharedPreferences {
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when a shared
|
||||
* preference is changed.
|
||||
*/
|
||||
public interface OnSharedPreferenceChangeListener {
|
||||
/**
|
||||
* Called when a shared preference is changed, added, or removed. This
|
||||
* may be called even if a preference is set to its existing value.
|
||||
*
|
||||
* <p>This callback will be run on your main thread.
|
||||
*
|
||||
* @param sharedPreferences The {@link SharedPreferences} that received
|
||||
* the change.
|
||||
* @param key The key of the preference that was changed, added, or
|
||||
* removed.
|
||||
*/
|
||||
void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface used for modifying values in a {@link SharedPreferences}
|
||||
* object. All changes you make in an editor are batched, and not copied
|
||||
* back to the original {@link SharedPreferences} until you call {@link #commit}
|
||||
* or {@link #apply}
|
||||
*/
|
||||
public interface Editor {
|
||||
/**
|
||||
* Set a String value in the preferences editor, to be written back once
|
||||
* {@link #commit} or {@link #apply} are called.
|
||||
*
|
||||
* @param key The name of the preference to modify.
|
||||
* @param value The new value for the preference. Passing {@code null}
|
||||
* for this argument is equivalent to calling {@link #remove(String)} with
|
||||
* this key.
|
||||
*
|
||||
* @return Returns a reference to the same Editor object, so you can
|
||||
* chain put calls together.
|
||||
*/
|
||||
Editor putString(String key, @Nullable String value);
|
||||
|
||||
/**
|
||||
* Set a set of String values in the preferences editor, to be written
|
||||
* back once {@link #commit} or {@link #apply} is called.
|
||||
*
|
||||
* @param key The name of the preference to modify.
|
||||
* @param values The set of new values for the preference. Passing {@code null}
|
||||
* for this argument is equivalent to calling {@link #remove(String)} with
|
||||
* this key.
|
||||
* @return Returns a reference to the same Editor object, so you can
|
||||
* chain put calls together.
|
||||
*/
|
||||
Editor putStringSet(String key, @Nullable Set<String> values);
|
||||
|
||||
/**
|
||||
* Set an int value in the preferences editor, to be written back once
|
||||
* {@link #commit} or {@link #apply} are called.
|
||||
*
|
||||
* @param key The name of the preference to modify.
|
||||
* @param value The new value for the preference.
|
||||
*
|
||||
* @return Returns a reference to the same Editor object, so you can
|
||||
* chain put calls together.
|
||||
*/
|
||||
Editor putInt(String key, int value);
|
||||
|
||||
/**
|
||||
* Set a long value in the preferences editor, to be written back once
|
||||
* {@link #commit} or {@link #apply} are called.
|
||||
*
|
||||
* @param key The name of the preference to modify.
|
||||
* @param value The new value for the preference.
|
||||
*
|
||||
* @return Returns a reference to the same Editor object, so you can
|
||||
* chain put calls together.
|
||||
*/
|
||||
Editor putLong(String key, long value);
|
||||
|
||||
/**
|
||||
* Set a float value in the preferences editor, to be written back once
|
||||
* {@link #commit} or {@link #apply} are called.
|
||||
*
|
||||
* @param key The name of the preference to modify.
|
||||
* @param value The new value for the preference.
|
||||
*
|
||||
* @return Returns a reference to the same Editor object, so you can
|
||||
* chain put calls together.
|
||||
*/
|
||||
Editor putFloat(String key, float value);
|
||||
|
||||
/**
|
||||
* Set a boolean value in the preferences editor, to be written back
|
||||
* once {@link #commit} or {@link #apply} are called.
|
||||
*
|
||||
* @param key The name of the preference to modify.
|
||||
* @param value The new value for the preference.
|
||||
*
|
||||
* @return Returns a reference to the same Editor object, so you can
|
||||
* chain put calls together.
|
||||
*/
|
||||
Editor putBoolean(String key, boolean value);
|
||||
/**
|
||||
* Mark in the editor that a preference value should be removed, which
|
||||
* will be done in the actual preferences once {@link #commit} is
|
||||
* called.
|
||||
*
|
||||
* <p>Note that when committing back to the preferences, all removals
|
||||
* are done first, regardless of whether you called remove before
|
||||
* or after put methods on this editor.
|
||||
*
|
||||
* @param key The name of the preference to remove.
|
||||
*
|
||||
* @return Returns a reference to the same Editor object, so you can
|
||||
* chain put calls together.
|
||||
*/
|
||||
Editor remove(String key);
|
||||
/**
|
||||
* Mark in the editor to remove <em>all</em> values from the
|
||||
* preferences. Once commit is called, the only remaining preferences
|
||||
* will be any that you have defined in this editor.
|
||||
*
|
||||
* <p>Note that when committing back to the preferences, the clear
|
||||
* is done first, regardless of whether you called clear before
|
||||
* or after put methods on this editor.
|
||||
*
|
||||
* @return Returns a reference to the same Editor object, so you can
|
||||
* chain put calls together.
|
||||
*/
|
||||
Editor clear();
|
||||
/**
|
||||
* Commit your preferences changes back from this Editor to the
|
||||
* {@link SharedPreferences} object it is editing. This atomically
|
||||
* performs the requested modifications, replacing whatever is currently
|
||||
* in the SharedPreferences.
|
||||
*
|
||||
* <p>Note that when two editors are modifying preferences at the same
|
||||
* time, the last one to call commit wins.
|
||||
*
|
||||
* <p>If you don't care about the return value and you're
|
||||
* using this from your application's main thread, consider
|
||||
* using {@link #apply} instead.
|
||||
*
|
||||
* @return Returns true if the new values were successfully written
|
||||
* to persistent storage.
|
||||
*/
|
||||
boolean commit();
|
||||
/**
|
||||
* Commit your preferences changes back from this Editor to the
|
||||
* {@link SharedPreferences} object it is editing. This atomically
|
||||
* performs the requested modifications, replacing whatever is currently
|
||||
* in the SharedPreferences.
|
||||
*
|
||||
* <p>Note that when two editors are modifying preferences at the same
|
||||
* time, the last one to call apply wins.
|
||||
*
|
||||
* <p>Unlike {@link #commit}, which writes its preferences out
|
||||
* to persistent storage synchronously, {@link #apply}
|
||||
* commits its changes to the in-memory
|
||||
* {@link SharedPreferences} immediately but starts an
|
||||
* asynchronous commit to disk and you won't be notified of
|
||||
* any failures. If another editor on this
|
||||
* {@link SharedPreferences} does a regular {@link #commit}
|
||||
* while a {@link #apply} is still outstanding, the
|
||||
* {@link #commit} will block until all async commits are
|
||||
* completed as well as the commit itself.
|
||||
*
|
||||
* <p>As {@link SharedPreferences} instances are singletons within
|
||||
* a process, it's safe to replace any instance of {@link #commit} with
|
||||
* {@link #apply} if you were already ignoring the return value.
|
||||
*
|
||||
* <p>You don't need to worry about Android component
|
||||
* lifecycles and their interaction with <code>apply()</code>
|
||||
* writing to disk. The framework makes sure in-flight disk
|
||||
* writes from <code>apply()</code> complete before switching
|
||||
* states.
|
||||
*
|
||||
* <p class='note'>The SharedPreferences.Editor interface
|
||||
* isn't expected to be implemented directly. However, if you
|
||||
* previously did implement it and are now getting errors
|
||||
* about missing <code>apply()</code>, you can simply call
|
||||
* {@link #commit} from <code>apply()</code>.
|
||||
*/
|
||||
void apply();
|
||||
}
|
||||
/**
|
||||
* Retrieve all values from the preferences.
|
||||
*
|
||||
* <p>Note that you <em>must not</em> modify the collection returned
|
||||
* by this method, or alter any of its contents. The consistency of your
|
||||
* stored data is not guaranteed if you do.
|
||||
*
|
||||
* @return Returns a map containing a list of pairs key/value representing
|
||||
* the preferences.
|
||||
*
|
||||
* @throws NullPointerException
|
||||
*/
|
||||
Map<String, ?> getAll();
|
||||
/**
|
||||
* Retrieve a String value from the preferences.
|
||||
*
|
||||
* @param key The name of the preference to retrieve.
|
||||
* @param defValue Value to return if this preference does not exist.
|
||||
*
|
||||
* @return Returns the preference value if it exists, or defValue. Throws
|
||||
* ClassCastException if there is a preference with this name that is not
|
||||
* a String.
|
||||
*
|
||||
* @throws ClassCastException
|
||||
*/
|
||||
@Nullable
|
||||
String getString(String key, @Nullable String defValue);
|
||||
|
||||
/**
|
||||
* Retrieve a set of String values from the preferences.
|
||||
*
|
||||
* <p>Note that you <em>must not</em> modify the set instance returned
|
||||
* by this call. The consistency of the stored data is not guaranteed
|
||||
* if you do, nor is your ability to modify the instance at all.
|
||||
*
|
||||
* @param key The name of the preference to retrieve.
|
||||
* @param defValues Values to return if this preference does not exist.
|
||||
*
|
||||
* @return Returns the preference values if they exist, or defValues.
|
||||
* Throws ClassCastException if there is a preference with this name
|
||||
* that is not a Set.
|
||||
*
|
||||
* @throws ClassCastException
|
||||
*/
|
||||
@Nullable
|
||||
Set<String> getStringSet(String key, @Nullable Set<String> defValues);
|
||||
|
||||
/**
|
||||
* Retrieve an int value from the preferences.
|
||||
*
|
||||
* @param key The name of the preference to retrieve.
|
||||
* @param defValue Value to return if this preference does not exist.
|
||||
*
|
||||
* @return Returns the preference value if it exists, or defValue. Throws
|
||||
* ClassCastException if there is a preference with this name that is not
|
||||
* an int.
|
||||
*
|
||||
* @throws ClassCastException
|
||||
*/
|
||||
int getInt(String key, int defValue);
|
||||
|
||||
/**
|
||||
* Retrieve a long value from the preferences.
|
||||
*
|
||||
* @param key The name of the preference to retrieve.
|
||||
* @param defValue Value to return if this preference does not exist.
|
||||
*
|
||||
* @return Returns the preference value if it exists, or defValue. Throws
|
||||
* ClassCastException if there is a preference with this name that is not
|
||||
* a long.
|
||||
*
|
||||
* @throws ClassCastException
|
||||
*/
|
||||
long getLong(String key, long defValue);
|
||||
|
||||
/**
|
||||
* Retrieve a float value from the preferences.
|
||||
*
|
||||
* @param key The name of the preference to retrieve.
|
||||
* @param defValue Value to return if this preference does not exist.
|
||||
*
|
||||
* @return Returns the preference value if it exists, or defValue. Throws
|
||||
* ClassCastException if there is a preference with this name that is not
|
||||
* a float.
|
||||
*
|
||||
* @throws ClassCastException
|
||||
*/
|
||||
float getFloat(String key, float defValue);
|
||||
|
||||
/**
|
||||
* Retrieve a boolean value from the preferences.
|
||||
*
|
||||
* @param key The name of the preference to retrieve.
|
||||
* @param defValue Value to return if this preference does not exist.
|
||||
*
|
||||
* @return Returns the preference value if it exists, or defValue. Throws
|
||||
* ClassCastException if there is a preference with this name that is not
|
||||
* a boolean.
|
||||
*
|
||||
* @throws ClassCastException
|
||||
*/
|
||||
boolean getBoolean(String key, boolean defValue);
|
||||
/**
|
||||
* Checks whether the preferences contains a preference.
|
||||
*
|
||||
* @param key The name of the preference to check.
|
||||
* @return Returns true if the preference exists in the preferences,
|
||||
* otherwise false.
|
||||
*/
|
||||
boolean contains(String key);
|
||||
|
||||
/**
|
||||
* Create a new Editor for these preferences, through which you can make
|
||||
* modifications to the data in the preferences and atomically commit those
|
||||
* changes back to the SharedPreferences object.
|
||||
*
|
||||
* <p>Note that you <em>must</em> call {@link Editor#commit} to have any
|
||||
* changes you perform in the Editor actually show up in the
|
||||
* SharedPreferences.
|
||||
*
|
||||
* @return Returns a new instance of the {@link Editor} interface, allowing
|
||||
* you to modify the values in this SharedPreferences object.
|
||||
*/
|
||||
Editor edit();
|
||||
|
||||
/**
|
||||
* Registers a callback to be invoked when a change happens to a preference.
|
||||
*
|
||||
* <p class="caution"><strong>Caution:</strong> The preference manager does
|
||||
* not currently store a strong reference to the listener. You must store a
|
||||
* strong reference to the listener, or it will be susceptible to garbage
|
||||
* collection. We recommend you keep a reference to the listener in the
|
||||
* instance data of an object that will exist as long as you need the
|
||||
* listener.</p>
|
||||
*
|
||||
* @param listener The callback that will run.
|
||||
* @see #unregisterOnSharedPreferenceChangeListener
|
||||
*/
|
||||
void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener);
|
||||
|
||||
/**
|
||||
* Unregisters a previous callback.
|
||||
*
|
||||
* @param listener The callback that should be unregistered.
|
||||
* @see #registerOnSharedPreferenceChangeListener
|
||||
*/
|
||||
void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener);
|
||||
}
|
@ -0,0 +1,999 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.content.pm;
|
||||
import android.annotation.SystemApi;
|
||||
import android.annotation.TestApi;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.Comparator;
|
||||
/**
|
||||
* Information you can retrieve about a particular application. This
|
||||
* corresponds to information collected from the AndroidManifest.xml's
|
||||
* <application> tag.
|
||||
*/
|
||||
public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
|
||||
/**
|
||||
* Default task affinity of all activities in this application. See
|
||||
* {@link ActivityInfo#taskAffinity} for more information. This comes
|
||||
* from the "taskAffinity" attribute.
|
||||
*/
|
||||
public String taskAffinity;
|
||||
|
||||
/**
|
||||
* Optional name of a permission required to be able to access this
|
||||
* application's components. From the "permission" attribute.
|
||||
*/
|
||||
public String permission;
|
||||
|
||||
/**
|
||||
* The name of the process this application should run in. From the
|
||||
* "process" attribute or, if not set, the same as
|
||||
* <var>packageName</var>.
|
||||
*/
|
||||
public String processName;
|
||||
|
||||
/**
|
||||
* Class implementing the Application object. From the "class"
|
||||
* attribute.
|
||||
*/
|
||||
public String className;
|
||||
|
||||
/**
|
||||
* A style resource identifier (in the package's resources) of the
|
||||
* description of an application. From the "description" attribute
|
||||
* or, if not set, 0.
|
||||
*/
|
||||
public int descriptionRes;
|
||||
|
||||
/**
|
||||
* A style resource identifier (in the package's resources) of the
|
||||
* default visual theme of the application. From the "theme" attribute
|
||||
* or, if not set, 0.
|
||||
*/
|
||||
public int theme;
|
||||
|
||||
/**
|
||||
* Class implementing the Application's manage space
|
||||
* functionality. From the "manageSpaceActivity"
|
||||
* attribute. This is an optional attribute and will be null if
|
||||
* applications don't specify it in their manifest
|
||||
*/
|
||||
public String manageSpaceActivityName;
|
||||
|
||||
/**
|
||||
* Class implementing the Application's backup functionality. From
|
||||
* the "backupAgent" attribute. This is an optional attribute and
|
||||
* will be null if the application does not specify it in its manifest.
|
||||
*
|
||||
* <p>If android:allowBackup is set to false, this attribute is ignored.
|
||||
*/
|
||||
public String backupAgentName;
|
||||
/**
|
||||
* An optional attribute that indicates the app supports automatic backup of app data.
|
||||
* <p>0 is the default and means the app's entire data folder + managed external storage will
|
||||
* be backed up;
|
||||
* Any negative value indicates the app does not support full-data backup, though it may still
|
||||
* want to participate via the traditional key/value backup API;
|
||||
* A positive number specifies an xml resource in which the application has defined its backup
|
||||
* include/exclude criteria.
|
||||
* <p>If android:allowBackup is set to false, this attribute is ignored.
|
||||
*
|
||||
* @see android.content.Context#getNoBackupFilesDir()
|
||||
* @see #FLAG_ALLOW_BACKUP
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public int fullBackupContent = 0;
|
||||
/**
|
||||
* The default extra UI options for activities in this application.
|
||||
* Set from the {@link android.R.attr#uiOptions} attribute in the
|
||||
* activity's manifest.
|
||||
*/
|
||||
public int uiOptions = 0;
|
||||
/**
|
||||
* Value for {@link #flags}: if set, this application is installed in the
|
||||
* device's system image.
|
||||
*/
|
||||
public static final int FLAG_SYSTEM = 1<<0;
|
||||
|
||||
/**
|
||||
* Value for {@link #flags}: set to true if this application would like to
|
||||
* allow debugging of its
|
||||
* code, even when installed on a non-development system. Comes
|
||||
* from {@link android.R.styleable#AndroidManifestApplication_debuggable
|
||||
* android:debuggable} of the <application> tag.
|
||||
*/
|
||||
public static final int FLAG_DEBUGGABLE = 1<<1;
|
||||
|
||||
/**
|
||||
* Value for {@link #flags}: set to true if this application has code
|
||||
* associated with it. Comes
|
||||
* from {@link android.R.styleable#AndroidManifestApplication_hasCode
|
||||
* android:hasCode} of the <application> tag.
|
||||
*/
|
||||
public static final int FLAG_HAS_CODE = 1<<2;
|
||||
|
||||
/**
|
||||
* Value for {@link #flags}: set to true if this application is persistent.
|
||||
* Comes from {@link android.R.styleable#AndroidManifestApplication_persistent
|
||||
* android:persistent} of the <application> tag.
|
||||
*/
|
||||
public static final int FLAG_PERSISTENT = 1<<3;
|
||||
/**
|
||||
* Value for {@link #flags}: set to true if this application holds the
|
||||
* {@link android.Manifest.permission#FACTORY_TEST} permission and the
|
||||
* device is running in factory test mode.
|
||||
*/
|
||||
public static final int FLAG_FACTORY_TEST = 1<<4;
|
||||
/**
|
||||
* Value for {@link #flags}: default value for the corresponding ActivityInfo flag.
|
||||
* Comes from {@link android.R.styleable#AndroidManifestApplication_allowTaskReparenting
|
||||
* android:allowTaskReparenting} of the <application> tag.
|
||||
*/
|
||||
public static final int FLAG_ALLOW_TASK_REPARENTING = 1<<5;
|
||||
|
||||
/**
|
||||
* Value for {@link #flags}: default value for the corresponding ActivityInfo flag.
|
||||
* Comes from {@link android.R.styleable#AndroidManifestApplication_allowClearUserData
|
||||
* android:allowClearUserData} of the <application> tag.
|
||||
*/
|
||||
public static final int FLAG_ALLOW_CLEAR_USER_DATA = 1<<6;
|
||||
|
||||
/**
|
||||
* Value for {@link #flags}: this is set if this application has been
|
||||
* installed as an update to a built-in system application.
|
||||
*/
|
||||
public static final int FLAG_UPDATED_SYSTEM_APP = 1<<7;
|
||||
|
||||
/**
|
||||
* Value for {@link #flags}: this is set if the application has specified
|
||||
* {@link android.R.styleable#AndroidManifestApplication_testOnly
|
||||
* android:testOnly} to be true.
|
||||
*/
|
||||
public static final int FLAG_TEST_ONLY = 1<<8;
|
||||
/**
|
||||
* Value for {@link #flags}: true when the application's window can be
|
||||
* reduced in size for smaller screens. Corresponds to
|
||||
* {@link android.R.styleable#AndroidManifestSupportsScreens_smallScreens
|
||||
* android:smallScreens}.
|
||||
*/
|
||||
public static final int FLAG_SUPPORTS_SMALL_SCREENS = 1<<9;
|
||||
|
||||
/**
|
||||
* Value for {@link #flags}: true when the application's window can be
|
||||
* displayed on normal screens. Corresponds to
|
||||
* {@link android.R.styleable#AndroidManifestSupportsScreens_normalScreens
|
||||
* android:normalScreens}.
|
||||
*/
|
||||
public static final int FLAG_SUPPORTS_NORMAL_SCREENS = 1<<10;
|
||||
|
||||
/**
|
||||
* Value for {@link #flags}: true when the application's window can be
|
||||
* increased in size for larger screens. Corresponds to
|
||||
* {@link android.R.styleable#AndroidManifestSupportsScreens_largeScreens
|
||||
* android:largeScreens}.
|
||||
*/
|
||||
public static final int FLAG_SUPPORTS_LARGE_SCREENS = 1<<11;
|
||||
|
||||
/**
|
||||
* Value for {@link #flags}: true when the application knows how to adjust
|
||||
* its UI for different screen sizes. Corresponds to
|
||||
* {@link android.R.styleable#AndroidManifestSupportsScreens_resizeable
|
||||
* android:resizeable}.
|
||||
*/
|
||||
public static final int FLAG_RESIZEABLE_FOR_SCREENS = 1<<12;
|
||||
|
||||
/**
|
||||
* Value for {@link #flags}: true when the application knows how to
|
||||
* accomodate different screen densities. Corresponds to
|
||||
* {@link android.R.styleable#AndroidManifestSupportsScreens_anyDensity
|
||||
* android:anyDensity}.
|
||||
*/
|
||||
public static final int FLAG_SUPPORTS_SCREEN_DENSITIES = 1<<13;
|
||||
|
||||
/**
|
||||
* Value for {@link #flags}: set to true if this application would like to
|
||||
* request the VM to operate under the safe mode. Comes from
|
||||
* {@link android.R.styleable#AndroidManifestApplication_vmSafeMode
|
||||
* android:vmSafeMode} of the <application> tag.
|
||||
*/
|
||||
public static final int FLAG_VM_SAFE_MODE = 1<<14;
|
||||
/**
|
||||
* Value for {@link #flags}: set to <code>false</code> if the application does not wish
|
||||
* to permit any OS-driven backups of its data; <code>true</code> otherwise.
|
||||
*
|
||||
* <p>Comes from the
|
||||
* {@link android.R.styleable#AndroidManifestApplication_allowBackup android:allowBackup}
|
||||
* attribute of the <application> tag.
|
||||
*/
|
||||
public static final int FLAG_ALLOW_BACKUP = 1<<15;
|
||||
/**
|
||||
* Value for {@link #flags}: set to <code>false</code> if the application must be kept
|
||||
* in memory following a full-system restore operation; <code>true</code> otherwise.
|
||||
* Ordinarily, during a full system restore operation each application is shut down
|
||||
* following execution of its agent's onRestore() method. Setting this attribute to
|
||||
* <code>false</code> prevents this. Most applications will not need to set this attribute.
|
||||
*
|
||||
* <p>If
|
||||
* {@link android.R.styleable#AndroidManifestApplication_allowBackup android:allowBackup}
|
||||
* is set to <code>false</code> or no
|
||||
* {@link android.R.styleable#AndroidManifestApplication_backupAgent android:backupAgent}
|
||||
* is specified, this flag will be ignored.
|
||||
*
|
||||
* <p>Comes from the
|
||||
* {@link android.R.styleable#AndroidManifestApplication_killAfterRestore android:killAfterRestore}
|
||||
* attribute of the <application> tag.
|
||||
*/
|
||||
public static final int FLAG_KILL_AFTER_RESTORE = 1<<16;
|
||||
/**
|
||||
* Value for {@link #flags}: Set to <code>true</code> if the application's backup
|
||||
* agent claims to be able to handle restore data even "from the future,"
|
||||
* i.e. from versions of the application with a versionCode greater than
|
||||
* the one currently installed on the device. <i>Use with caution!</i> By default
|
||||
* this attribute is <code>false</code> and the Backup Manager will ensure that data
|
||||
* from "future" versions of the application are never supplied during a restore operation.
|
||||
*
|
||||
* <p>If
|
||||
* {@link android.R.styleable#AndroidManifestApplication_allowBackup android:allowBackup}
|
||||
* is set to <code>false</code> or no
|
||||
* {@link android.R.styleable#AndroidManifestApplication_backupAgent android:backupAgent}
|
||||
* is specified, this flag will be ignored.
|
||||
*
|
||||
* <p>Comes from the
|
||||
* {@link android.R.styleable#AndroidManifestApplication_restoreAnyVersion android:restoreAnyVersion}
|
||||
* attribute of the <application> tag.
|
||||
*/
|
||||
public static final int FLAG_RESTORE_ANY_VERSION = 1<<17;
|
||||
/**
|
||||
* Value for {@link #flags}: Set to true if the application is
|
||||
* currently installed on external/removable/unprotected storage. Such
|
||||
* applications may not be available if their storage is not currently
|
||||
* mounted. When the storage it is on is not available, it will look like
|
||||
* the application has been uninstalled (its .apk is no longer available)
|
||||
* but its persistent data is not removed.
|
||||
*/
|
||||
public static final int FLAG_EXTERNAL_STORAGE = 1<<18;
|
||||
/**
|
||||
* Value for {@link #flags}: true when the application's window can be
|
||||
* increased in size for extra large screens. Corresponds to
|
||||
* {@link android.R.styleable#AndroidManifestSupportsScreens_xlargeScreens
|
||||
* android:xlargeScreens}.
|
||||
*/
|
||||
public static final int FLAG_SUPPORTS_XLARGE_SCREENS = 1<<19;
|
||||
|
||||
/**
|
||||
* Value for {@link #flags}: true when the application has requested a
|
||||
* large heap for its processes. Corresponds to
|
||||
* {@link android.R.styleable#AndroidManifestApplication_largeHeap
|
||||
* android:largeHeap}.
|
||||
*/
|
||||
public static final int FLAG_LARGE_HEAP = 1<<20;
|
||||
/**
|
||||
* Value for {@link #flags}: true if this application's package is in
|
||||
* the stopped state.
|
||||
*/
|
||||
public static final int FLAG_STOPPED = 1<<21;
|
||||
/**
|
||||
* Value for {@link #flags}: true when the application is willing to support
|
||||
* RTL (right to left). All activities will inherit this value.
|
||||
*
|
||||
* Set from the {@link android.R.attr#supportsRtl} attribute in the
|
||||
* activity's manifest.
|
||||
*
|
||||
* Default value is false (no support for RTL).
|
||||
*/
|
||||
public static final int FLAG_SUPPORTS_RTL = 1<<22;
|
||||
/**
|
||||
* Value for {@link #flags}: true if the application is currently
|
||||
* installed for the calling user.
|
||||
*/
|
||||
public static final int FLAG_INSTALLED = 1<<23;
|
||||
/**
|
||||
* Value for {@link #flags}: true if the application only has its
|
||||
* data installed; the application package itself does not currently
|
||||
* exist on the device.
|
||||
*/
|
||||
public static final int FLAG_IS_DATA_ONLY = 1<<24;
|
||||
/**
|
||||
* Value for {@link #flags}: true if the application was declared to be a game, or
|
||||
* false if it is a non-game application.
|
||||
*/
|
||||
public static final int FLAG_IS_GAME = 1<<25;
|
||||
/**
|
||||
* Value for {@link #flags}: {@code true} if the application asks that only
|
||||
* full-data streaming backups of its data be performed even though it defines
|
||||
* a {@link android.app.backup.BackupAgent BackupAgent}, which normally
|
||||
* indicates that the app will manage its backed-up data via incremental
|
||||
* key/value updates.
|
||||
*/
|
||||
public static final int FLAG_FULL_BACKUP_ONLY = 1<<26;
|
||||
/**
|
||||
* Value for {@link #flags}: {@code true} if the application may use cleartext network traffic
|
||||
* (e.g., HTTP rather than HTTPS; WebSockets rather than WebSockets Secure; XMPP, IMAP, STMP
|
||||
* without STARTTLS or TLS). If {@code false}, the app declares that it does not intend to use
|
||||
* cleartext network traffic, in which case platform components (e.g., HTTP stacks,
|
||||
* {@code DownloadManager}, {@code MediaPlayer}) will refuse app's requests to use cleartext
|
||||
* traffic. Third-party libraries are encouraged to honor this flag as well.
|
||||
*
|
||||
* <p>NOTE: {@code WebView} does not honor this flag.
|
||||
*
|
||||
* <p>This flag is ignored on Android N and above if an Android Network Security Config is
|
||||
* present.
|
||||
*
|
||||
* <p>This flag comes from
|
||||
* {@link android.R.styleable#AndroidManifestApplication_usesCleartextTraffic
|
||||
* android:usesCleartextTraffic} of the <application> tag.
|
||||
*/
|
||||
public static final int FLAG_USES_CLEARTEXT_TRAFFIC = 1<<27;
|
||||
/**
|
||||
* When set installer extracts native libs from .apk files.
|
||||
*/
|
||||
public static final int FLAG_EXTRACT_NATIVE_LIBS = 1<<28;
|
||||
/**
|
||||
* Value for {@link #flags}: {@code true} when the application's rendering
|
||||
* should be hardware accelerated.
|
||||
*/
|
||||
public static final int FLAG_HARDWARE_ACCELERATED = 1<<29;
|
||||
/**
|
||||
* Value for {@link #flags}: true if this application's package is in
|
||||
* the suspended state.
|
||||
*/
|
||||
public static final int FLAG_SUSPENDED = 1<<30;
|
||||
/**
|
||||
* Value for {@link #flags}: true if code from this application will need to be
|
||||
* loaded into other applications' processes. On devices that support multiple
|
||||
* instruction sets, this implies the code might be loaded into a process that's
|
||||
* using any of the devices supported instruction sets.
|
||||
*
|
||||
* <p> The system might treat such applications specially, for eg., by
|
||||
* extracting the application's native libraries for all supported instruction
|
||||
* sets or by compiling the application's dex code for all supported instruction
|
||||
* sets.
|
||||
*/
|
||||
public static final int FLAG_MULTIARCH = 1 << 31;
|
||||
/**
|
||||
* Flags associated with the application. Any combination of
|
||||
* {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE},
|
||||
* {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and
|
||||
* {@link #FLAG_ALLOW_TASK_REPARENTING}
|
||||
* {@link #FLAG_ALLOW_CLEAR_USER_DATA}, {@link #FLAG_UPDATED_SYSTEM_APP},
|
||||
* {@link #FLAG_TEST_ONLY}, {@link #FLAG_SUPPORTS_SMALL_SCREENS},
|
||||
* {@link #FLAG_SUPPORTS_NORMAL_SCREENS},
|
||||
* {@link #FLAG_SUPPORTS_LARGE_SCREENS}, {@link #FLAG_SUPPORTS_XLARGE_SCREENS},
|
||||
* {@link #FLAG_RESIZEABLE_FOR_SCREENS},
|
||||
* {@link #FLAG_SUPPORTS_SCREEN_DENSITIES}, {@link #FLAG_VM_SAFE_MODE},
|
||||
* {@link #FLAG_ALLOW_BACKUP}, {@link #FLAG_KILL_AFTER_RESTORE},
|
||||
* {@link #FLAG_RESTORE_ANY_VERSION}, {@link #FLAG_EXTERNAL_STORAGE},
|
||||
* {@link #FLAG_LARGE_HEAP}, {@link #FLAG_STOPPED},
|
||||
* {@link #FLAG_SUPPORTS_RTL}, {@link #FLAG_INSTALLED},
|
||||
* {@link #FLAG_IS_DATA_ONLY}, {@link #FLAG_IS_GAME},
|
||||
* {@link #FLAG_FULL_BACKUP_ONLY}, {@link #FLAG_USES_CLEARTEXT_TRAFFIC},
|
||||
* {@link #FLAG_MULTIARCH}.
|
||||
*/
|
||||
public int flags = 0;
|
||||
/**
|
||||
* Value for {@link #privateFlags}: true if the application is hidden via restrictions and for
|
||||
* most purposes is considered as not installed.
|
||||
* {@hide}
|
||||
*/
|
||||
public static final int PRIVATE_FLAG_HIDDEN = 1<<0;
|
||||
/**
|
||||
* Value for {@link #privateFlags}: set to <code>true</code> if the application
|
||||
* has reported that it is heavy-weight, and thus can not participate in
|
||||
* the normal application lifecycle.
|
||||
*
|
||||
* <p>Comes from the
|
||||
* android.R.styleable#AndroidManifestApplication_cantSaveState
|
||||
* attribute of the <application> tag.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public static final int PRIVATE_FLAG_CANT_SAVE_STATE = 1<<1;
|
||||
/**
|
||||
* Value for {@link #privateFlags}: Set to true if the application has been
|
||||
* installed using the forward lock option.
|
||||
*
|
||||
* NOTE: DO NOT CHANGE THIS VALUE! It is saved in packages.xml.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public static final int PRIVATE_FLAG_FORWARD_LOCK = 1<<2;
|
||||
/**
|
||||
* Value for {@link #privateFlags}: set to {@code true} if the application
|
||||
* is permitted to hold privileged permissions.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public static final int PRIVATE_FLAG_PRIVILEGED = 1<<3;
|
||||
/**
|
||||
* Value for {@link #privateFlags}: {@code true} if the application has any IntentFiler
|
||||
* with some data URI using HTTP or HTTPS with an associated VIEW action.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public static final int PRIVATE_FLAG_HAS_DOMAIN_URLS = 1<<4;
|
||||
/**
|
||||
* When set, the default data storage directory for this app is pointed at
|
||||
* the device-protected location.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE = 1 << 5;
|
||||
/**
|
||||
* When set, assume that all components under the given app are direct boot
|
||||
* aware, unless otherwise specified.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int PRIVATE_FLAG_DIRECT_BOOT_AWARE = 1 << 6;
|
||||
/**
|
||||
* Value for {@link #privateFlags}: set to {@code true} if the application
|
||||
* is AutoPlay.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public static final int PRIVATE_FLAG_AUTOPLAY = 1 << 7;
|
||||
/**
|
||||
* When set, at least one component inside this application is direct boot
|
||||
* aware.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE = 1 << 8;
|
||||
/**
|
||||
* Value for {@link #flags}: {@code true} if the application is blocked via restrictions
|
||||
* and for most purposes is considered as not installed.
|
||||
* {@hide}
|
||||
*/
|
||||
public static final int PRIVATE_FLAG_EPHEMERAL = 1 << 9;
|
||||
/**
|
||||
* When set, signals that the application is required for the system user and should not be
|
||||
* uninstalled.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER = 1 << 10;
|
||||
/**
|
||||
* When set, the activities associated with this application are resizeable by default.
|
||||
* @see android.R.styleable#AndroidManifestActivity_resizeableActivity
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int PRIVATE_FLAG_RESIZEABLE_ACTIVITIES = 1 << 11;
|
||||
/**
|
||||
* Value for {@link #privateFlags}: {@code true} means the OS should go ahead and
|
||||
* run full-data backup operations for the app even when it is in a
|
||||
* foreground-equivalent run state. Defaults to {@code false} if unspecified.
|
||||
* @hide
|
||||
*/
|
||||
public static final int PRIVATE_FLAG_BACKUP_IN_FOREGROUND = 1 << 12;
|
||||
/**
|
||||
* Private/hidden flags. See {@code PRIVATE_FLAG_...} constants.
|
||||
* {@hide}
|
||||
*/
|
||||
public int privateFlags;
|
||||
/**
|
||||
* The required smallest screen width the application can run on. If 0,
|
||||
* nothing has been specified. Comes from
|
||||
* {@link android.R.styleable#AndroidManifestSupportsScreens_requiresSmallestWidthDp
|
||||
* android:requiresSmallestWidthDp} attribute of the <supports-screens> tag.
|
||||
*/
|
||||
public int requiresSmallestWidthDp = 0;
|
||||
/**
|
||||
* The maximum smallest screen width the application is designed for. If 0,
|
||||
* nothing has been specified. Comes from
|
||||
* {@link android.R.styleable#AndroidManifestSupportsScreens_compatibleWidthLimitDp
|
||||
* android:compatibleWidthLimitDp} attribute of the <supports-screens> tag.
|
||||
*/
|
||||
public int compatibleWidthLimitDp = 0;
|
||||
/**
|
||||
* The maximum smallest screen width the application will work on. If 0,
|
||||
* nothing has been specified. Comes from
|
||||
* {@link android.R.styleable#AndroidManifestSupportsScreens_largestWidthLimitDp
|
||||
* android:largestWidthLimitDp} attribute of the <supports-screens> tag.
|
||||
*/
|
||||
public int largestWidthLimitDp = 0;
|
||||
/** {@hide} */
|
||||
public String volumeUuid;
|
||||
/** {@hide} */
|
||||
public String scanSourceDir;
|
||||
/** {@hide} */
|
||||
public String scanPublicSourceDir;
|
||||
/**
|
||||
* Full path to the base APK for this application.
|
||||
*/
|
||||
public String sourceDir;
|
||||
/**
|
||||
* Full path to the publicly available parts of {@link #sourceDir},
|
||||
* including resources and manifest. This may be different from
|
||||
* {@link #sourceDir} if an application is forward locked.
|
||||
*/
|
||||
public String publicSourceDir;
|
||||
/**
|
||||
* Full paths to zero or more split APKs that, when combined with the base
|
||||
* APK defined in {@link #sourceDir}, form a complete application.
|
||||
*/
|
||||
public String[] splitSourceDirs;
|
||||
/**
|
||||
* Full path to the publicly available parts of {@link #splitSourceDirs},
|
||||
* including resources and manifest. This may be different from
|
||||
* {@link #splitSourceDirs} if an application is forward locked.
|
||||
*/
|
||||
public String[] splitPublicSourceDirs;
|
||||
/**
|
||||
* Full paths to the locations of extra resource packages this application
|
||||
* uses. This field is only used if there are extra resource packages,
|
||||
* otherwise it is null.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public String[] resourceDirs;
|
||||
/**
|
||||
* String retrieved from the seinfo tag found in selinux policy. This value
|
||||
* can be overridden with a value set through the mac_permissions.xml policy
|
||||
* construct. This value is useful in setting an SELinux security context on
|
||||
* the process as well as its data directory. The String default is being used
|
||||
* here to represent a catchall label when no policy matches.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public String seinfo = "default";
|
||||
/**
|
||||
* Paths to all shared libraries this application is linked against. This
|
||||
* field is only set if the {@link PackageManager#GET_SHARED_LIBRARY_FILES
|
||||
* PackageManager.GET_SHARED_LIBRARY_FILES} flag was used when retrieving
|
||||
* the structure.
|
||||
*/
|
||||
public String[] sharedLibraryFiles;
|
||||
|
||||
/**
|
||||
* Full path to the default directory assigned to the package for its
|
||||
* persistent data.
|
||||
*/
|
||||
public String dataDir;
|
||||
/**
|
||||
* Full path to the device-protected directory assigned to the package for
|
||||
* its persistent data.
|
||||
*
|
||||
* @see Context#createDeviceProtectedStorageContext()
|
||||
*/
|
||||
public String deviceProtectedDataDir;
|
||||
/** @removed */
|
||||
@Deprecated
|
||||
public String deviceEncryptedDataDir;
|
||||
/**
|
||||
* Full path to the credential-protected directory assigned to the package
|
||||
* for its persistent data.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public String credentialProtectedDataDir;
|
||||
/** @removed */
|
||||
@Deprecated
|
||||
public String credentialEncryptedDataDir;
|
||||
/**
|
||||
* Full path to the directory where native JNI libraries are stored.
|
||||
*/
|
||||
public String nativeLibraryDir;
|
||||
/**
|
||||
* Full path where unpacked native libraries for {@link #secondaryCpuAbi}
|
||||
* are stored, if present.
|
||||
*
|
||||
* The main reason this exists is for bundled multi-arch apps, where
|
||||
* it's not trivial to calculate the location of libs for the secondary abi
|
||||
* given the location of the primary.
|
||||
*
|
||||
* TODO: Change the layout of bundled installs so that we can use
|
||||
* nativeLibraryRootDir & nativeLibraryRootRequiresIsa there as well.
|
||||
* (e.g {@code [ "/system/app-lib/Foo/arm", "/system/app-lib/Foo/arm64" ]}
|
||||
* instead of {@code [ "/system/lib/Foo", "/system/lib64/Foo" ]}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public String secondaryNativeLibraryDir;
|
||||
/**
|
||||
* The root path where unpacked native libraries are stored.
|
||||
* <p>
|
||||
* When {@link #nativeLibraryRootRequiresIsa} is set, the libraries are
|
||||
* placed in ISA-specific subdirectories under this path, otherwise the
|
||||
* libraries are placed directly at this path.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public String nativeLibraryRootDir;
|
||||
/**
|
||||
* Flag indicating that ISA must be appended to
|
||||
* {@link #nativeLibraryRootDir} to be useful.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public boolean nativeLibraryRootRequiresIsa;
|
||||
/**
|
||||
* The primary ABI that this application requires, This is inferred from the ABIs
|
||||
* of the native JNI libraries the application bundles. Will be {@code null}
|
||||
* if this application does not require any particular ABI.
|
||||
*
|
||||
* If non-null, the application will always be launched with this ABI.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public String primaryCpuAbi;
|
||||
/**
|
||||
* The secondary ABI for this application. Might be non-null for multi-arch
|
||||
* installs. The application itself never uses this ABI, but other applications that
|
||||
* use its code might.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public String secondaryCpuAbi;
|
||||
/**
|
||||
* The kernel user-ID that has been assigned to this application;
|
||||
* currently this is not a unique ID (multiple applications can have
|
||||
* the same uid).
|
||||
*/
|
||||
public int uid;
|
||||
|
||||
/**
|
||||
* The minimum SDK version this application can run on. It will not run
|
||||
* on earlier versions.
|
||||
*/
|
||||
public int minSdkVersion;
|
||||
/**
|
||||
* The minimum SDK version this application targets. It may run on earlier
|
||||
* versions, but it knows how to work with any new behavior added at this
|
||||
* version. Will be {@link android.os.Build.VERSION_CODES#CUR_DEVELOPMENT}
|
||||
* if this is a development build and the app is targeting that. You should
|
||||
* compare that this number is >= the SDK version number at which your
|
||||
* behavior was introduced.
|
||||
*/
|
||||
public int targetSdkVersion;
|
||||
/**
|
||||
* The app's declared version code.
|
||||
* @hide
|
||||
*/
|
||||
public int versionCode;
|
||||
/**
|
||||
* When false, indicates that all components within this application are
|
||||
* considered disabled, regardless of their individually set enabled status.
|
||||
*/
|
||||
public boolean enabled = true;
|
||||
/**
|
||||
* For convenient access to the current enabled setting of this app.
|
||||
* @hide
|
||||
*/
|
||||
public int enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
|
||||
/**
|
||||
* For convenient access to package's install location.
|
||||
* @hide
|
||||
*/
|
||||
public int installLocation = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
|
||||
/**
|
||||
* Resource file providing the application's Network Security Config.
|
||||
* @hide
|
||||
*/
|
||||
public int networkSecurityConfigRes;
|
||||
/**
|
||||
* @return true if "supportsRtl" has been set to true in the AndroidManifest
|
||||
* @hide
|
||||
*/
|
||||
public boolean hasRtlSupport() {
|
||||
return (flags & FLAG_SUPPORTS_RTL) == FLAG_SUPPORTS_RTL;
|
||||
}
|
||||
/** {@hide} */
|
||||
public boolean hasCode() {
|
||||
return (flags & FLAG_HAS_CODE) != 0;
|
||||
}
|
||||
public static class DisplayNameComparator
|
||||
implements Comparator<ApplicationInfo> {
|
||||
public DisplayNameComparator(PackageManager pm) {
|
||||
mPM = pm;
|
||||
}
|
||||
public final int compare(ApplicationInfo aa, ApplicationInfo ab) {
|
||||
CharSequence sa = mPM.getApplicationLabel(aa);
|
||||
if (sa == null) {
|
||||
sa = aa.packageName;
|
||||
}
|
||||
CharSequence sb = mPM.getApplicationLabel(ab);
|
||||
if (sb == null) {
|
||||
sb = ab.packageName;
|
||||
}
|
||||
|
||||
return sCollator.compare(sa.toString(), sb.toString());
|
||||
}
|
||||
private final Collator sCollator = Collator.getInstance();
|
||||
private PackageManager mPM;
|
||||
}
|
||||
public ApplicationInfo() {
|
||||
}
|
||||
|
||||
public ApplicationInfo(ApplicationInfo orig) {
|
||||
super(orig);
|
||||
taskAffinity = orig.taskAffinity;
|
||||
permission = orig.permission;
|
||||
processName = orig.processName;
|
||||
className = orig.className;
|
||||
theme = orig.theme;
|
||||
flags = orig.flags;
|
||||
privateFlags = orig.privateFlags;
|
||||
requiresSmallestWidthDp = orig.requiresSmallestWidthDp;
|
||||
compatibleWidthLimitDp = orig.compatibleWidthLimitDp;
|
||||
largestWidthLimitDp = orig.largestWidthLimitDp;
|
||||
volumeUuid = orig.volumeUuid;
|
||||
scanSourceDir = orig.scanSourceDir;
|
||||
scanPublicSourceDir = orig.scanPublicSourceDir;
|
||||
sourceDir = orig.sourceDir;
|
||||
publicSourceDir = orig.publicSourceDir;
|
||||
splitSourceDirs = orig.splitSourceDirs;
|
||||
splitPublicSourceDirs = orig.splitPublicSourceDirs;
|
||||
nativeLibraryDir = orig.nativeLibraryDir;
|
||||
secondaryNativeLibraryDir = orig.secondaryNativeLibraryDir;
|
||||
nativeLibraryRootDir = orig.nativeLibraryRootDir;
|
||||
nativeLibraryRootRequiresIsa = orig.nativeLibraryRootRequiresIsa;
|
||||
primaryCpuAbi = orig.primaryCpuAbi;
|
||||
secondaryCpuAbi = orig.secondaryCpuAbi;
|
||||
resourceDirs = orig.resourceDirs;
|
||||
seinfo = orig.seinfo;
|
||||
sharedLibraryFiles = orig.sharedLibraryFiles;
|
||||
dataDir = orig.dataDir;
|
||||
deviceEncryptedDataDir = deviceProtectedDataDir = orig.deviceProtectedDataDir;
|
||||
credentialEncryptedDataDir = credentialProtectedDataDir = orig.credentialProtectedDataDir;
|
||||
uid = orig.uid;
|
||||
minSdkVersion = orig.minSdkVersion;
|
||||
targetSdkVersion = orig.targetSdkVersion;
|
||||
versionCode = orig.versionCode;
|
||||
enabled = orig.enabled;
|
||||
enabledSetting = orig.enabledSetting;
|
||||
installLocation = orig.installLocation;
|
||||
manageSpaceActivityName = orig.manageSpaceActivityName;
|
||||
descriptionRes = orig.descriptionRes;
|
||||
uiOptions = orig.uiOptions;
|
||||
backupAgentName = orig.backupAgentName;
|
||||
fullBackupContent = orig.fullBackupContent;
|
||||
networkSecurityConfigRes = orig.networkSecurityConfigRes;
|
||||
}
|
||||
public String toString() {
|
||||
return "ApplicationInfo{"
|
||||
+ Integer.toHexString(System.identityHashCode(this))
|
||||
+ " " + packageName + "}";
|
||||
}
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
public void writeToParcel(Parcel dest, int parcelableFlags) {
|
||||
super.writeToParcel(dest, parcelableFlags);
|
||||
dest.writeString(taskAffinity);
|
||||
dest.writeString(permission);
|
||||
dest.writeString(processName);
|
||||
dest.writeString(className);
|
||||
dest.writeInt(theme);
|
||||
dest.writeInt(flags);
|
||||
dest.writeInt(privateFlags);
|
||||
dest.writeInt(requiresSmallestWidthDp);
|
||||
dest.writeInt(compatibleWidthLimitDp);
|
||||
dest.writeInt(largestWidthLimitDp);
|
||||
dest.writeString(volumeUuid);
|
||||
dest.writeString(scanSourceDir);
|
||||
dest.writeString(scanPublicSourceDir);
|
||||
dest.writeString(sourceDir);
|
||||
dest.writeString(publicSourceDir);
|
||||
dest.writeStringArray(splitSourceDirs);
|
||||
dest.writeStringArray(splitPublicSourceDirs);
|
||||
dest.writeString(nativeLibraryDir);
|
||||
dest.writeString(secondaryNativeLibraryDir);
|
||||
dest.writeString(nativeLibraryRootDir);
|
||||
dest.writeInt(nativeLibraryRootRequiresIsa ? 1 : 0);
|
||||
dest.writeString(primaryCpuAbi);
|
||||
dest.writeString(secondaryCpuAbi);
|
||||
dest.writeStringArray(resourceDirs);
|
||||
dest.writeString(seinfo);
|
||||
dest.writeStringArray(sharedLibraryFiles);
|
||||
dest.writeString(dataDir);
|
||||
dest.writeString(deviceProtectedDataDir);
|
||||
dest.writeString(credentialProtectedDataDir);
|
||||
dest.writeInt(uid);
|
||||
dest.writeInt(minSdkVersion);
|
||||
dest.writeInt(targetSdkVersion);
|
||||
dest.writeInt(versionCode);
|
||||
dest.writeInt(enabled ? 1 : 0);
|
||||
dest.writeInt(enabledSetting);
|
||||
dest.writeInt(installLocation);
|
||||
dest.writeString(manageSpaceActivityName);
|
||||
dest.writeString(backupAgentName);
|
||||
dest.writeInt(descriptionRes);
|
||||
dest.writeInt(uiOptions);
|
||||
dest.writeInt(fullBackupContent);
|
||||
dest.writeInt(networkSecurityConfigRes);
|
||||
}
|
||||
public static final Parcelable.Creator<ApplicationInfo> CREATOR
|
||||
= new Parcelable.Creator<ApplicationInfo>() {
|
||||
public ApplicationInfo createFromParcel(Parcel source) {
|
||||
return new ApplicationInfo(source);
|
||||
}
|
||||
public ApplicationInfo[] newArray(int size) {
|
||||
return new ApplicationInfo[size];
|
||||
}
|
||||
};
|
||||
private ApplicationInfo(Parcel source) {
|
||||
super(source);
|
||||
taskAffinity = source.readString();
|
||||
permission = source.readString();
|
||||
processName = source.readString();
|
||||
className = source.readString();
|
||||
theme = source.readInt();
|
||||
flags = source.readInt();
|
||||
privateFlags = source.readInt();
|
||||
requiresSmallestWidthDp = source.readInt();
|
||||
compatibleWidthLimitDp = source.readInt();
|
||||
largestWidthLimitDp = source.readInt();
|
||||
volumeUuid = source.readString();
|
||||
scanSourceDir = source.readString();
|
||||
scanPublicSourceDir = source.readString();
|
||||
sourceDir = source.readString();
|
||||
publicSourceDir = source.readString();
|
||||
nativeLibraryDir = source.readString();
|
||||
secondaryNativeLibraryDir = source.readString();
|
||||
nativeLibraryRootDir = source.readString();
|
||||
nativeLibraryRootRequiresIsa = source.readInt() != 0;
|
||||
primaryCpuAbi = source.readString();
|
||||
secondaryCpuAbi = source.readString();
|
||||
seinfo = source.readString();
|
||||
dataDir = source.readString();
|
||||
deviceEncryptedDataDir = deviceProtectedDataDir = source.readString();
|
||||
credentialEncryptedDataDir = credentialProtectedDataDir = source.readString();
|
||||
uid = source.readInt();
|
||||
minSdkVersion = source.readInt();
|
||||
targetSdkVersion = source.readInt();
|
||||
versionCode = source.readInt();
|
||||
enabled = source.readInt() != 0;
|
||||
enabledSetting = source.readInt();
|
||||
installLocation = source.readInt();
|
||||
manageSpaceActivityName = source.readString();
|
||||
backupAgentName = source.readString();
|
||||
descriptionRes = source.readInt();
|
||||
uiOptions = source.readInt();
|
||||
fullBackupContent = source.readInt();
|
||||
networkSecurityConfigRes = source.readInt();
|
||||
}
|
||||
/**
|
||||
* Retrieve the textual description of the application. This
|
||||
* will call back on the given PackageManager to load the description from
|
||||
* the application.
|
||||
*
|
||||
* @param pm A PackageManager from which the label can be loaded; usually
|
||||
* the PackageManager from which you originally retrieved this item.
|
||||
*
|
||||
* @return Returns a CharSequence containing the application's description.
|
||||
* If there is no description, null is returned.
|
||||
*/
|
||||
public CharSequence loadDescription(PackageManager pm) {
|
||||
if (descriptionRes != 0) {
|
||||
CharSequence label = pm.getText(packageName, descriptionRes, this);
|
||||
if (label != null) {
|
||||
return label;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Disable compatibility mode
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public void disableCompatibilityMode() {
|
||||
flags |= (FLAG_SUPPORTS_LARGE_SCREENS | FLAG_SUPPORTS_NORMAL_SCREENS |
|
||||
FLAG_SUPPORTS_SMALL_SCREENS | FLAG_RESIZEABLE_FOR_SCREENS |
|
||||
FLAG_SUPPORTS_SCREEN_DENSITIES | FLAG_SUPPORTS_XLARGE_SCREENS);
|
||||
}
|
||||
|
||||
private boolean isPackageUnavailable(PackageManager pm) {
|
||||
try {
|
||||
return pm.getPackageInfo(packageName, 0) == null;
|
||||
} catch (NameNotFoundException ex) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public boolean isForwardLocked() {
|
||||
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0;
|
||||
}
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public boolean isSystemApp() {
|
||||
return (flags & ApplicationInfo.FLAG_SYSTEM) != 0;
|
||||
}
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public boolean isPrivilegedApp() {
|
||||
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
|
||||
}
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public boolean isUpdatedSystemApp() {
|
||||
return (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
|
||||
}
|
||||
/** @hide */
|
||||
public boolean isInternal() {
|
||||
return (flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0;
|
||||
}
|
||||
/** @hide */
|
||||
public boolean isExternalAsec() {
|
||||
return TextUtils.isEmpty(volumeUuid)
|
||||
&& (flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
|
||||
}
|
||||
/** @hide */
|
||||
public boolean isDefaultToDeviceProtectedStorage() {
|
||||
return (privateFlags
|
||||
& ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) != 0;
|
||||
}
|
||||
/** @hide */
|
||||
public boolean isDirectBootAware() {
|
||||
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE) != 0;
|
||||
}
|
||||
/** @hide */
|
||||
public boolean isPartiallyDirectBootAware() {
|
||||
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE) != 0;
|
||||
}
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public boolean isAutoPlayApp() {
|
||||
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_AUTOPLAY) != 0;
|
||||
}
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public boolean isEphemeralApp() {
|
||||
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_EPHEMERAL) != 0;
|
||||
}
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public boolean isRequiredForSystemUser() {
|
||||
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER) != 0;
|
||||
}
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
protected ApplicationInfo getApplicationInfo() {
|
||||
return this;
|
||||
}
|
||||
/** {@hide} */ public void setCodePath(String codePath) { scanSourceDir = codePath; }
|
||||
/** {@hide} */ public void setBaseCodePath(String baseCodePath) { sourceDir = baseCodePath; }
|
||||
/** {@hide} */ public void setSplitCodePaths(String[] splitCodePaths) { splitSourceDirs = splitCodePaths; }
|
||||
/** {@hide} */ public void setResourcePath(String resourcePath) { scanPublicSourceDir = resourcePath; }
|
||||
/** {@hide} */ public void setBaseResourcePath(String baseResourcePath) { publicSourceDir = baseResourcePath; }
|
||||
/** {@hide} */ public void setSplitResourcePaths(String[] splitResourcePaths) { splitPublicSourceDirs = splitResourcePaths; }
|
||||
/** {@hide} */ public String getCodePath() { return scanSourceDir; }
|
||||
/** {@hide} */ public String getBaseCodePath() { return sourceDir; }
|
||||
/** {@hide} */ public String[] getSplitCodePaths() { return splitSourceDirs; }
|
||||
/** {@hide} */ public String getResourcePath() { return scanPublicSourceDir; }
|
||||
/** {@hide} */ public String getBaseResourcePath() { return publicSourceDir; }
|
||||
/** {@hide} */ public String[] getSplitResourcePaths() { return splitSourceDirs; }
|
||||
}
|
132
AndroidCompat/src/main/java/android/content/pm/FeatureInfo.java
Normal file
132
AndroidCompat/src/main/java/android/content/pm/FeatureInfo.java
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.content.pm;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
/**
|
||||
* Definition of a single optional hardware or software feature of an Android
|
||||
* device.
|
||||
* <p>
|
||||
* This object is used to represent both features supported by a device and
|
||||
* features requested by an app. Apps can request that certain features be
|
||||
* available as a prerequisite to being installed through the
|
||||
* {@code uses-feature} tag in their manifests.
|
||||
* <p>
|
||||
* Starting in {@link android.os.Build.VERSION_CODES#N}, features can have a
|
||||
* version, which must always be backwards compatible. That is, a device
|
||||
* claiming to support version 3 of a specific feature must support apps
|
||||
* requesting version 1 of that feature.
|
||||
*/
|
||||
public class FeatureInfo implements Parcelable {
|
||||
/**
|
||||
* The name of this feature, for example "android.hardware.camera". If
|
||||
* this is null, then this is an OpenGL ES version feature as described
|
||||
* in {@link #reqGlEsVersion}.
|
||||
*/
|
||||
public String name;
|
||||
/**
|
||||
* If this object represents a feature supported by a device, this is the
|
||||
* maximum version of this feature supported by the device. The device
|
||||
* implicitly supports all older versions of this feature.
|
||||
* <p>
|
||||
* If this object represents a feature requested by an app, this is the
|
||||
* minimum version of the feature required by the app.
|
||||
* <p>
|
||||
* When a feature version is undefined by a device, it's assumed to be
|
||||
* version 0.
|
||||
*/
|
||||
public int version;
|
||||
/**
|
||||
* Default value for {@link #reqGlEsVersion};
|
||||
*/
|
||||
public static final int GL_ES_VERSION_UNDEFINED = 0;
|
||||
|
||||
/**
|
||||
* The GLES version used by an application. The upper order 16 bits represent the
|
||||
* major version and the lower order 16 bits the minor version. Only valid
|
||||
* if {@link #name} is null.
|
||||
*/
|
||||
public int reqGlEsVersion;
|
||||
/**
|
||||
* Set on {@link #flags} if this feature has been required by the application.
|
||||
*/
|
||||
public static final int FLAG_REQUIRED = 0x0001;
|
||||
|
||||
/**
|
||||
* Additional flags. May be zero or more of {@link #FLAG_REQUIRED}.
|
||||
*/
|
||||
public int flags;
|
||||
|
||||
public FeatureInfo() {
|
||||
}
|
||||
public FeatureInfo(FeatureInfo orig) {
|
||||
name = orig.name;
|
||||
version = orig.version;
|
||||
reqGlEsVersion = orig.reqGlEsVersion;
|
||||
flags = orig.flags;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
if (name != null) {
|
||||
return "FeatureInfo{"
|
||||
+ Integer.toHexString(System.identityHashCode(this))
|
||||
+ " " + name + " v=" + version + " fl=0x" + Integer.toHexString(flags) + "}";
|
||||
} else {
|
||||
return "FeatureInfo{"
|
||||
+ Integer.toHexString(System.identityHashCode(this))
|
||||
+ " glEsVers=" + getGlEsVersion()
|
||||
+ " fl=0x" + Integer.toHexString(flags) + "}";
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int parcelableFlags) {
|
||||
dest.writeString(name);
|
||||
dest.writeInt(version);
|
||||
dest.writeInt(reqGlEsVersion);
|
||||
dest.writeInt(flags);
|
||||
}
|
||||
public static final Creator<FeatureInfo> CREATOR = new Creator<FeatureInfo>() {
|
||||
@Override
|
||||
public FeatureInfo createFromParcel(Parcel source) {
|
||||
return new FeatureInfo(source);
|
||||
}
|
||||
@Override
|
||||
public FeatureInfo[] newArray(int size) {
|
||||
return new FeatureInfo[size];
|
||||
}
|
||||
};
|
||||
private FeatureInfo(Parcel source) {
|
||||
name = source.readString();
|
||||
version = source.readInt();
|
||||
reqGlEsVersion = source.readInt();
|
||||
flags = source.readInt();
|
||||
}
|
||||
/**
|
||||
* This method extracts the major and minor version of reqGLEsVersion attribute
|
||||
* and returns it as a string. Say reqGlEsVersion value of 0x00010002 is returned
|
||||
* as 1.2
|
||||
* @return String representation of the reqGlEsVersion attribute
|
||||
*/
|
||||
public String getGlEsVersion() {
|
||||
int major = ((reqGlEsVersion & 0xffff0000) >> 16);
|
||||
int minor = reqGlEsVersion & 0x0000ffff;
|
||||
return String.valueOf(major)+"."+String.valueOf(minor);
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.content.pm;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemApi;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import kotlin.NotImplementedError;
|
||||
|
||||
/**
|
||||
* This class represents the state of an instant app. Instant apps can
|
||||
* be installed or uninstalled. If the app is installed you can call
|
||||
* {@link #getApplicationInfo()} to get the app info, otherwise this
|
||||
* class provides APIs to get basic app info for showing it in the UI,
|
||||
* such as permissions, label, package name.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public final class InstantAppInfo implements Parcelable {
|
||||
private final ApplicationInfo mApplicationInfo;
|
||||
private final String mPackageName;
|
||||
private final CharSequence mLabelText;
|
||||
private final String[] mRequestedPermissions;
|
||||
private final String[] mGrantedPermissions;
|
||||
public InstantAppInfo(ApplicationInfo appInfo,
|
||||
String[] requestedPermissions, String[] grantedPermissions) {
|
||||
mApplicationInfo = appInfo;
|
||||
mPackageName = null;
|
||||
mLabelText = null;
|
||||
mRequestedPermissions = requestedPermissions;
|
||||
mGrantedPermissions = grantedPermissions;
|
||||
}
|
||||
public InstantAppInfo(String packageName, CharSequence label,
|
||||
String[] requestedPermissions, String[] grantedPermissions) {
|
||||
mApplicationInfo = null;
|
||||
mPackageName = packageName;
|
||||
mLabelText = label;
|
||||
mRequestedPermissions = requestedPermissions;
|
||||
mGrantedPermissions = grantedPermissions;
|
||||
}
|
||||
private InstantAppInfo(Parcel parcel) {
|
||||
throw new NotImplementedError();
|
||||
}
|
||||
/**
|
||||
* @return The application info if the app is installed,
|
||||
* <code>null</code> otherwise,
|
||||
*/
|
||||
public @Nullable ApplicationInfo getApplicationInfo() {
|
||||
return mApplicationInfo;
|
||||
}
|
||||
/**
|
||||
* @return The package name.
|
||||
*/
|
||||
public @NonNull String getPackageName() {
|
||||
if (mApplicationInfo != null) {
|
||||
return mApplicationInfo.packageName;
|
||||
}
|
||||
return mPackageName;
|
||||
}
|
||||
/**
|
||||
* @param packageManager Package manager for loading resources.
|
||||
* @return Loads the label if the app is installed or returns the cached one otherwise.
|
||||
*/
|
||||
public @NonNull CharSequence loadLabel(@NonNull PackageManager packageManager) {
|
||||
if (mApplicationInfo != null) {
|
||||
return mApplicationInfo.loadLabel(packageManager);
|
||||
}
|
||||
return mLabelText;
|
||||
}
|
||||
/**
|
||||
* @param packageManager Package manager for loading resources.
|
||||
* @return Loads the icon if the app is installed or returns the cached one otherwise.
|
||||
*/
|
||||
public @NonNull Drawable loadIcon(@NonNull PackageManager packageManager) {
|
||||
if (mApplicationInfo != null) {
|
||||
return mApplicationInfo.loadIcon(packageManager);
|
||||
}
|
||||
return packageManager.getInstantAppIcon(mPackageName);
|
||||
}
|
||||
/**
|
||||
* @return The requested permissions.
|
||||
*/
|
||||
public @Nullable String[] getRequestedPermissions() {
|
||||
return mRequestedPermissions;
|
||||
}
|
||||
/**
|
||||
* @return The granted permissions.
|
||||
*/
|
||||
public @Nullable String[] getGrantedPermissions() {
|
||||
return mGrantedPermissions;
|
||||
}
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
throw new NotImplementedError();
|
||||
}
|
||||
public static final Creator<InstantAppInfo> CREATOR =
|
||||
new Creator<InstantAppInfo>() {
|
||||
@Override
|
||||
public InstantAppInfo createFromParcel(Parcel parcel) {
|
||||
return new InstantAppInfo(parcel);
|
||||
}
|
||||
@Override
|
||||
public InstantAppInfo[] newArray(int size) {
|
||||
return new InstantAppInfo[0];
|
||||
}
|
||||
};
|
||||
}
|
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.content.pm;
|
||||
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
|
||||
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
|
||||
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
|
||||
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
|
||||
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
|
||||
import android.annotation.SystemApi;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import com.android.internal.util.XmlUtils;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
/**
|
||||
* The {@link com.android.server.pm.PackageManagerService} maintains some
|
||||
* {@link IntentFilterVerificationInfo}s for each domain / package name.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public final class IntentFilterVerificationInfo implements Parcelable {
|
||||
private static final String TAG = IntentFilterVerificationInfo.class.getName();
|
||||
private static final String TAG_DOMAIN = "domain";
|
||||
private static final String ATTR_DOMAIN_NAME = "name";
|
||||
private static final String ATTR_PACKAGE_NAME = "packageName";
|
||||
private static final String ATTR_STATUS = "status";
|
||||
private ArraySet<String> mDomains = new ArraySet<>();
|
||||
private String mPackageName;
|
||||
private int mMainStatus;
|
||||
/** @hide */
|
||||
public IntentFilterVerificationInfo() {
|
||||
mPackageName = null;
|
||||
mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
|
||||
}
|
||||
/** @hide */
|
||||
public IntentFilterVerificationInfo(String packageName, ArraySet<String> domains) {
|
||||
mPackageName = packageName;
|
||||
mDomains = domains;
|
||||
mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
|
||||
}
|
||||
/** @hide */
|
||||
public IntentFilterVerificationInfo(XmlPullParser parser)
|
||||
throws IOException, XmlPullParserException {
|
||||
readFromXml(parser);
|
||||
}
|
||||
/** @hide */
|
||||
public IntentFilterVerificationInfo(Parcel source) {
|
||||
readFromParcel(source);
|
||||
}
|
||||
public String getPackageName() {
|
||||
return mPackageName;
|
||||
}
|
||||
public int getStatus() {
|
||||
return mMainStatus;
|
||||
}
|
||||
/** @hide */
|
||||
public void setStatus(int s) {
|
||||
if (s >= INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED &&
|
||||
s <= INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) {
|
||||
mMainStatus = s;
|
||||
} else {
|
||||
Log.w(TAG, "Trying to set a non supported status: " + s);
|
||||
}
|
||||
}
|
||||
public Set<String> getDomains() {
|
||||
return mDomains;
|
||||
}
|
||||
/** @hide */
|
||||
public void setDomains(ArraySet<String> list) {
|
||||
mDomains = list;
|
||||
}
|
||||
/** @hide */
|
||||
public String getDomainsString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String str : mDomains) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(" ");
|
||||
}
|
||||
sb.append(str);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
String getStringFromXml(XmlPullParser parser, String attribute, String defaultValue) {
|
||||
String value = parser.getAttributeValue(null, attribute);
|
||||
if (value == null) {
|
||||
String msg = "Missing element under " + TAG +": " + attribute + " at " +
|
||||
parser.getPositionDescription();
|
||||
Log.w(TAG, msg);
|
||||
return defaultValue;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
int getIntFromXml(XmlPullParser parser, String attribute, int defaultValue) {
|
||||
String value = parser.getAttributeValue(null, attribute);
|
||||
if (TextUtils.isEmpty(value)) {
|
||||
String msg = "Missing element under " + TAG +": " + attribute + " at " +
|
||||
parser.getPositionDescription();
|
||||
Log.w(TAG, msg);
|
||||
return defaultValue;
|
||||
} else {
|
||||
return Integer.parseInt(value);
|
||||
}
|
||||
}
|
||||
/** @hide */
|
||||
public void readFromXml(XmlPullParser parser) throws XmlPullParserException,
|
||||
IOException {
|
||||
mPackageName = getStringFromXml(parser, ATTR_PACKAGE_NAME, null);
|
||||
if (mPackageName == null) {
|
||||
Log.e(TAG, "Package name cannot be null!");
|
||||
}
|
||||
int status = getIntFromXml(parser, ATTR_STATUS, -1);
|
||||
if (status == -1) {
|
||||
Log.e(TAG, "Unknown status value: " + status);
|
||||
}
|
||||
mMainStatus = status;
|
||||
int outerDepth = parser.getDepth();
|
||||
int type;
|
||||
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
&& (type != XmlPullParser.END_TAG
|
||||
|| parser.getDepth() > outerDepth)) {
|
||||
if (type == XmlPullParser.END_TAG
|
||||
|| type == XmlPullParser.TEXT) {
|
||||
continue;
|
||||
}
|
||||
String tagName = parser.getName();
|
||||
if (tagName.equals(TAG_DOMAIN)) {
|
||||
String name = getStringFromXml(parser, ATTR_DOMAIN_NAME, null);
|
||||
if (!TextUtils.isEmpty(name)) {
|
||||
mDomains.add(name);
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "Unknown tag parsing IntentFilter: " + tagName);
|
||||
}
|
||||
XmlUtils.skipCurrentTag(parser);
|
||||
}
|
||||
}
|
||||
/** @hide */
|
||||
public void writeToXml(XmlSerializer serializer) throws IOException {
|
||||
serializer.attribute(null, ATTR_PACKAGE_NAME, mPackageName);
|
||||
serializer.attribute(null, ATTR_STATUS, String.valueOf(mMainStatus));
|
||||
for (String str : mDomains) {
|
||||
serializer.startTag(null, TAG_DOMAIN);
|
||||
serializer.attribute(null, ATTR_DOMAIN_NAME, str);
|
||||
serializer.endTag(null, TAG_DOMAIN);
|
||||
}
|
||||
}
|
||||
/** @hide */
|
||||
public String getStatusString() {
|
||||
return getStatusStringFromValue(((long)mMainStatus) << 32);
|
||||
}
|
||||
/** @hide */
|
||||
public static String getStatusStringFromValue(long val) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
switch ((int)(val >> 32)) {
|
||||
case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS:
|
||||
sb.append("always : ");
|
||||
sb.append(Long.toHexString(val & 0x00000000FFFFFFFF));
|
||||
break;
|
||||
case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK:
|
||||
sb.append("ask");
|
||||
break;
|
||||
case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER:
|
||||
sb.append("never");
|
||||
break;
|
||||
case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK:
|
||||
sb.append("always-ask");
|
||||
break;
|
||||
case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED:
|
||||
default:
|
||||
sb.append("undefined");
|
||||
break;
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
private void readFromParcel(Parcel source) {
|
||||
mPackageName = source.readString();
|
||||
mMainStatus = source.readInt();
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
source.readStringList(list);
|
||||
mDomains.addAll(list);
|
||||
}
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(mPackageName);
|
||||
dest.writeInt(mMainStatus);
|
||||
dest.writeStringList(new ArrayList<>(mDomains));
|
||||
}
|
||||
public static final Creator<IntentFilterVerificationInfo> CREATOR =
|
||||
new Creator<IntentFilterVerificationInfo>() {
|
||||
public IntentFilterVerificationInfo createFromParcel(Parcel source) {
|
||||
return new IntentFilterVerificationInfo(source);
|
||||
}
|
||||
public IntentFilterVerificationInfo[] newArray(int size) {
|
||||
return new IntentFilterVerificationInfo[size];
|
||||
}
|
||||
};
|
||||
}
|
95
AndroidCompat/src/main/java/android/content/pm/KeySet.java
Normal file
95
AndroidCompat/src/main/java/android/content/pm/KeySet.java
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.content.pm;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
/**
|
||||
* Represents a {@code KeySet} that has been declared in the AndroidManifest.xml
|
||||
* file for the application. A {@code KeySet} can be used explicitly to
|
||||
* represent a trust relationship with other applications on the device.
|
||||
* @hide
|
||||
*/
|
||||
public class KeySet implements Parcelable {
|
||||
private IBinder token;
|
||||
/** @hide */
|
||||
public KeySet(IBinder token) {
|
||||
if (token == null) {
|
||||
throw new NullPointerException("null value for KeySet IBinder token");
|
||||
}
|
||||
this.token = token;
|
||||
}
|
||||
/** @hide */
|
||||
public IBinder getToken() {
|
||||
return token;
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof KeySet) {
|
||||
KeySet ks = (KeySet) o;
|
||||
return token == ks.token;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return token.hashCode();
|
||||
}
|
||||
/**
|
||||
* Implement Parcelable
|
||||
* @hide
|
||||
*/
|
||||
public static final Parcelable.Creator<KeySet> CREATOR
|
||||
= new Parcelable.Creator<KeySet>() {
|
||||
/**
|
||||
* Create a KeySet from a Parcel
|
||||
*
|
||||
* @param source The parcel containing the KeySet
|
||||
*/
|
||||
public KeySet createFromParcel(Parcel source) {
|
||||
return readFromParcel(source);
|
||||
}
|
||||
/**
|
||||
* Create an array of null KeySets
|
||||
*/
|
||||
public KeySet[] newArray(int size) {
|
||||
return new KeySet[size];
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
private static KeySet readFromParcel(Parcel in) {
|
||||
IBinder token = in.readStrongBinder();
|
||||
return new KeySet(token);
|
||||
}
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeStrongBinder(token);
|
||||
}
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
353
AndroidCompat/src/main/java/android/content/pm/PackageInfo.java
Normal file
353
AndroidCompat/src/main/java/android/content/pm/PackageInfo.java
Normal file
@ -0,0 +1,353 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.content.pm;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
/**
|
||||
* Overall information about the contents of a package. This corresponds
|
||||
* to all of the information collected from AndroidManifest.xml.
|
||||
*/
|
||||
public class PackageInfo implements Parcelable {
|
||||
/**
|
||||
* The name of this package. From the <manifest> tag's "name"
|
||||
* attribute.
|
||||
*/
|
||||
public String packageName;
|
||||
/**
|
||||
* The names of any installed split APKs for this package.
|
||||
*/
|
||||
public String[] splitNames;
|
||||
/**
|
||||
* The version number of this package, as specified by the <manifest>
|
||||
* tag's {@link android.R.styleable#AndroidManifest_versionCode versionCode}
|
||||
* attribute.
|
||||
*/
|
||||
public int versionCode;
|
||||
/**
|
||||
* The version name of this package, as specified by the <manifest>
|
||||
* tag's {@link android.R.styleable#AndroidManifest_versionName versionName}
|
||||
* attribute.
|
||||
*/
|
||||
public String versionName;
|
||||
/**
|
||||
* The revision number of the base APK for this package, as specified by the
|
||||
* <manifest> tag's
|
||||
* {@link android.R.styleable#AndroidManifest_revisionCode revisionCode}
|
||||
* attribute.
|
||||
*/
|
||||
public int baseRevisionCode;
|
||||
/**
|
||||
* The revision number of any split APKs for this package, as specified by
|
||||
* the <manifest> tag's
|
||||
* {@link android.R.styleable#AndroidManifest_revisionCode revisionCode}
|
||||
* attribute. Indexes are a 1:1 mapping against {@link #splitNames}.
|
||||
*/
|
||||
public int[] splitRevisionCodes;
|
||||
/**
|
||||
* The shared user ID name of this package, as specified by the <manifest>
|
||||
* tag's {@link android.R.styleable#AndroidManifest_sharedUserId sharedUserId}
|
||||
* attribute.
|
||||
*/
|
||||
public String sharedUserId;
|
||||
|
||||
/**
|
||||
* The shared user ID label of this package, as specified by the <manifest>
|
||||
* tag's {@link android.R.styleable#AndroidManifest_sharedUserLabel sharedUserLabel}
|
||||
* attribute.
|
||||
*/
|
||||
public int sharedUserLabel;
|
||||
|
||||
/**
|
||||
* Information collected from the <application> tag, or null if
|
||||
* there was none.
|
||||
*/
|
||||
public ApplicationInfo applicationInfo;
|
||||
|
||||
/**
|
||||
* The time at which the app was first installed. Units are as
|
||||
* per {@link System#currentTimeMillis()}.
|
||||
*/
|
||||
public long firstInstallTime;
|
||||
/**
|
||||
* The time at which the app was last updated. Units are as
|
||||
* per {@link System#currentTimeMillis()}.
|
||||
*/
|
||||
public long lastUpdateTime;
|
||||
/**
|
||||
* All kernel group-IDs that have been assigned to this package.
|
||||
* This is only filled in if the flag {@link PackageManager#GET_GIDS} was set.
|
||||
*/
|
||||
public int[] gids;
|
||||
/**
|
||||
* Array of all {@link android.R.styleable#AndroidManifestActivity
|
||||
* <activity>} tags included under <application>,
|
||||
* or null if there were none. This is only filled in if the flag
|
||||
* {@link PackageManager#GET_ACTIVITIES} was set.
|
||||
*/
|
||||
public ActivityInfo[] activities;
|
||||
/**
|
||||
* Array of all {@link android.R.styleable#AndroidManifestReceiver
|
||||
* <receiver>} tags included under <application>,
|
||||
* or null if there were none. This is only filled in if the flag
|
||||
* {@link PackageManager#GET_RECEIVERS} was set.
|
||||
*/
|
||||
public ActivityInfo[] receivers;
|
||||
/**
|
||||
* Array of all {@link android.R.styleable#AndroidManifestService
|
||||
* <service>} tags included under <application>,
|
||||
* or null if there were none. This is only filled in if the flag
|
||||
* {@link PackageManager#GET_SERVICES} was set.
|
||||
*/
|
||||
public ServiceInfo[] services;
|
||||
/**
|
||||
* Array of all {@link android.R.styleable#AndroidManifestProvider
|
||||
* <provider>} tags included under <application>,
|
||||
* or null if there were none. This is only filled in if the flag
|
||||
* {@link PackageManager#GET_PROVIDERS} was set.
|
||||
*/
|
||||
public ProviderInfo[] providers;
|
||||
/**
|
||||
* Array of all {@link android.R.styleable#AndroidManifestInstrumentation
|
||||
* <instrumentation>} tags included under <manifest>,
|
||||
* or null if there were none. This is only filled in if the flag
|
||||
* {@link PackageManager#GET_INSTRUMENTATION} was set.
|
||||
*/
|
||||
public InstrumentationInfo[] instrumentation;
|
||||
|
||||
/**
|
||||
* Array of all {@link android.R.styleable#AndroidManifestPermission
|
||||
* <permission>} tags included under <manifest>,
|
||||
* or null if there were none. This is only filled in if the flag
|
||||
* {@link PackageManager#GET_PERMISSIONS} was set.
|
||||
*/
|
||||
public PermissionInfo[] permissions;
|
||||
|
||||
/**
|
||||
* Array of all {@link android.R.styleable#AndroidManifestUsesPermission
|
||||
* <uses-permission>} tags included under <manifest>,
|
||||
* or null if there were none. This is only filled in if the flag
|
||||
* {@link PackageManager#GET_PERMISSIONS} was set. This list includes
|
||||
* all permissions requested, even those that were not granted or known
|
||||
* by the system at install time.
|
||||
*/
|
||||
public String[] requestedPermissions;
|
||||
|
||||
/**
|
||||
* Array of flags of all {@link android.R.styleable#AndroidManifestUsesPermission
|
||||
* <uses-permission>} tags included under <manifest>,
|
||||
* or null if there were none. This is only filled in if the flag
|
||||
* {@link PackageManager#GET_PERMISSIONS} was set. Each value matches
|
||||
* the corresponding entry in {@link #requestedPermissions}, and will have
|
||||
* the flag {@link #REQUESTED_PERMISSION_GRANTED} set as appropriate.
|
||||
*/
|
||||
public int[] requestedPermissionsFlags;
|
||||
/**
|
||||
* Flag for {@link #requestedPermissionsFlags}: the requested permission
|
||||
* is required for the application to run; the user can not optionally
|
||||
* disable it. Currently all permissions are required.
|
||||
*
|
||||
* @removed We do not support required permissions.
|
||||
*/
|
||||
public static final int REQUESTED_PERMISSION_REQUIRED = 1<<0;
|
||||
/**
|
||||
* Flag for {@link #requestedPermissionsFlags}: the requested permission
|
||||
* is currently granted to the application.
|
||||
*/
|
||||
public static final int REQUESTED_PERMISSION_GRANTED = 1<<1;
|
||||
/**
|
||||
* Array of all signatures read from the package file. This is only filled
|
||||
* in if the flag {@link PackageManager#GET_SIGNATURES} was set.
|
||||
*/
|
||||
public Signature[] signatures;
|
||||
|
||||
/**
|
||||
* Application specified preferred configuration
|
||||
* {@link android.R.styleable#AndroidManifestUsesConfiguration
|
||||
* <uses-configuration>} tags included under <manifest>,
|
||||
* or null if there were none. This is only filled in if the flag
|
||||
* {@link PackageManager#GET_CONFIGURATIONS} was set.
|
||||
*/
|
||||
public ConfigurationInfo[] configPreferences;
|
||||
/**
|
||||
* Features that this application has requested.
|
||||
*
|
||||
* @see FeatureInfo#FLAG_REQUIRED
|
||||
*/
|
||||
public FeatureInfo[] reqFeatures;
|
||||
/**
|
||||
* Groups of features that this application has requested.
|
||||
* Each group contains a set of features that are required.
|
||||
* A device must match the features listed in {@link #reqFeatures} and one
|
||||
* or more FeatureGroups in order to have satisfied the feature requirement.
|
||||
*
|
||||
* @see FeatureInfo#FLAG_REQUIRED
|
||||
*/
|
||||
public FeatureGroupInfo[] featureGroups;
|
||||
/**
|
||||
* Constant corresponding to <code>auto</code> in
|
||||
* the {@link android.R.attr#installLocation} attribute.
|
||||
* @hide
|
||||
*/
|
||||
public static final int INSTALL_LOCATION_UNSPECIFIED = -1;
|
||||
/**
|
||||
* Constant corresponding to <code>auto</code> in the
|
||||
* {@link android.R.attr#installLocation} attribute.
|
||||
*/
|
||||
public static final int INSTALL_LOCATION_AUTO = 0;
|
||||
/**
|
||||
* Constant corresponding to <code>internalOnly</code> in the
|
||||
* {@link android.R.attr#installLocation} attribute.
|
||||
*/
|
||||
public static final int INSTALL_LOCATION_INTERNAL_ONLY = 1;
|
||||
/**
|
||||
* Constant corresponding to <code>preferExternal</code> in the
|
||||
* {@link android.R.attr#installLocation} attribute.
|
||||
*/
|
||||
public static final int INSTALL_LOCATION_PREFER_EXTERNAL = 2;
|
||||
/**
|
||||
* The install location requested by the package. From the
|
||||
* {@link android.R.attr#installLocation} attribute, one of
|
||||
* {@link #INSTALL_LOCATION_AUTO}, {@link #INSTALL_LOCATION_INTERNAL_ONLY},
|
||||
* {@link #INSTALL_LOCATION_PREFER_EXTERNAL}
|
||||
*/
|
||||
public int installLocation = INSTALL_LOCATION_INTERNAL_ONLY;
|
||||
/** @hide */
|
||||
public boolean coreApp;
|
||||
/** @hide */
|
||||
public boolean requiredForAllUsers;
|
||||
/** @hide */
|
||||
public String restrictedAccountType;
|
||||
/** @hide */
|
||||
public String requiredAccountType;
|
||||
/**
|
||||
* What package, if any, this package will overlay.
|
||||
*
|
||||
* Package name of target package, or null.
|
||||
* @hide
|
||||
*/
|
||||
public String overlayTarget;
|
||||
public PackageInfo() {
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PackageInfo{"
|
||||
+ Integer.toHexString(System.identityHashCode(this))
|
||||
+ " " + packageName + "}";
|
||||
}
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int parcelableFlags) {
|
||||
dest.writeString(packageName);
|
||||
dest.writeStringArray(splitNames);
|
||||
dest.writeInt(versionCode);
|
||||
dest.writeString(versionName);
|
||||
dest.writeInt(baseRevisionCode);
|
||||
dest.writeIntArray(splitRevisionCodes);
|
||||
dest.writeString(sharedUserId);
|
||||
dest.writeInt(sharedUserLabel);
|
||||
if (applicationInfo != null) {
|
||||
dest.writeInt(1);
|
||||
applicationInfo.writeToParcel(dest, parcelableFlags);
|
||||
} else {
|
||||
dest.writeInt(0);
|
||||
}
|
||||
dest.writeLong(firstInstallTime);
|
||||
dest.writeLong(lastUpdateTime);
|
||||
dest.writeIntArray(gids);
|
||||
dest.writeTypedArray(activities, parcelableFlags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
|
||||
dest.writeTypedArray(receivers, parcelableFlags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
|
||||
dest.writeTypedArray(services, parcelableFlags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
|
||||
dest.writeTypedArray(providers, parcelableFlags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
|
||||
dest.writeTypedArray(instrumentation, parcelableFlags);
|
||||
dest.writeTypedArray(permissions, parcelableFlags);
|
||||
dest.writeStringArray(requestedPermissions);
|
||||
dest.writeIntArray(requestedPermissionsFlags);
|
||||
dest.writeTypedArray(signatures, parcelableFlags);
|
||||
dest.writeTypedArray(configPreferences, parcelableFlags);
|
||||
dest.writeTypedArray(reqFeatures, parcelableFlags);
|
||||
dest.writeTypedArray(featureGroups, parcelableFlags);
|
||||
dest.writeInt(installLocation);
|
||||
dest.writeInt(coreApp ? 1 : 0);
|
||||
dest.writeInt(requiredForAllUsers ? 1 : 0);
|
||||
dest.writeString(restrictedAccountType);
|
||||
dest.writeString(requiredAccountType);
|
||||
dest.writeString(overlayTarget);
|
||||
}
|
||||
public static final Parcelable.Creator<PackageInfo> CREATOR
|
||||
= new Parcelable.Creator<PackageInfo>() {
|
||||
@Override
|
||||
public PackageInfo createFromParcel(Parcel source) {
|
||||
return new PackageInfo(source);
|
||||
}
|
||||
@Override
|
||||
public PackageInfo[] newArray(int size) {
|
||||
return new PackageInfo[size];
|
||||
}
|
||||
};
|
||||
private PackageInfo(Parcel source) {
|
||||
packageName = source.readString();
|
||||
splitNames = source.createStringArray();
|
||||
versionCode = source.readInt();
|
||||
versionName = source.readString();
|
||||
baseRevisionCode = source.readInt();
|
||||
splitRevisionCodes = source.createIntArray();
|
||||
sharedUserId = source.readString();
|
||||
sharedUserLabel = source.readInt();
|
||||
int hasApp = source.readInt();
|
||||
if (hasApp != 0) {
|
||||
applicationInfo = ApplicationInfo.CREATOR.createFromParcel(source);
|
||||
}
|
||||
firstInstallTime = source.readLong();
|
||||
lastUpdateTime = source.readLong();
|
||||
gids = source.createIntArray();
|
||||
activities = source.createTypedArray(ActivityInfo.CREATOR);
|
||||
receivers = source.createTypedArray(ActivityInfo.CREATOR);
|
||||
services = source.createTypedArray(ServiceInfo.CREATOR);
|
||||
providers = source.createTypedArray(ProviderInfo.CREATOR);
|
||||
instrumentation = source.createTypedArray(InstrumentationInfo.CREATOR);
|
||||
permissions = source.createTypedArray(PermissionInfo.CREATOR);
|
||||
requestedPermissions = source.createStringArray();
|
||||
requestedPermissionsFlags = source.createIntArray();
|
||||
signatures = source.createTypedArray(Signature.CREATOR);
|
||||
configPreferences = source.createTypedArray(ConfigurationInfo.CREATOR);
|
||||
reqFeatures = source.createTypedArray(FeatureInfo.CREATOR);
|
||||
featureGroups = source.createTypedArray(FeatureGroupInfo.CREATOR);
|
||||
installLocation = source.readInt();
|
||||
coreApp = source.readInt() != 0;
|
||||
requiredForAllUsers = source.readInt() != 0;
|
||||
restrictedAccountType = source.readString();
|
||||
requiredAccountType = source.readString();
|
||||
overlayTarget = source.readString();
|
||||
// The component lists were flattened with the redundant ApplicationInfo
|
||||
// instances omitted. Distribute the canonical one here as appropriate.
|
||||
if (applicationInfo != null) {
|
||||
propagateApplicationInfo(applicationInfo, activities);
|
||||
propagateApplicationInfo(applicationInfo, receivers);
|
||||
propagateApplicationInfo(applicationInfo, services);
|
||||
propagateApplicationInfo(applicationInfo, providers);
|
||||
}
|
||||
}
|
||||
private void propagateApplicationInfo(ApplicationInfo appInfo, ComponentInfo[] components) {
|
||||
if (components != null) {
|
||||
for (ComponentInfo ci : components) {
|
||||
ci.applicationInfo = appInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,346 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.content.pm;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.util.Printer;
|
||||
import kotlin.NotImplementedError;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.Comparator;
|
||||
/**
|
||||
* Base class containing information common to all package items held by
|
||||
* the package manager. This provides a very common basic set of attributes:
|
||||
* a label, icon, and meta-data. This class is not intended
|
||||
* to be used by itself; it is simply here to share common definitions
|
||||
* between all items returned by the package manager. As such, it does not
|
||||
* itself implement Parcelable, but does provide convenience methods to assist
|
||||
* in the implementation of Parcelable in subclasses.
|
||||
*/
|
||||
public class PackageItemInfo {
|
||||
private static final float MAX_LABEL_SIZE_PX = 500f;
|
||||
/**
|
||||
* Public name of this item. From the "android:name" attribute.
|
||||
*/
|
||||
public String name;
|
||||
|
||||
/**
|
||||
* Name of the package that this item is in.
|
||||
*/
|
||||
public String packageName;
|
||||
|
||||
/**
|
||||
* A string resource identifier (in the package's resources) of this
|
||||
* component's label. From the "label" attribute or, if not set, 0.
|
||||
*/
|
||||
public int labelRes;
|
||||
|
||||
/**
|
||||
* The string provided in the AndroidManifest file, if any. You
|
||||
* probably don't want to use this. You probably want
|
||||
* {@link PackageManager#getApplicationLabel}
|
||||
*/
|
||||
public CharSequence nonLocalizedLabel;
|
||||
|
||||
/**
|
||||
* A drawable resource identifier (in the package's resources) of this
|
||||
* component's icon. From the "icon" attribute or, if not set, 0.
|
||||
*/
|
||||
public int icon;
|
||||
|
||||
/**
|
||||
* A drawable resource identifier (in the package's resources) of this
|
||||
* component's banner. From the "banner" attribute or, if not set, 0.
|
||||
*/
|
||||
public int banner;
|
||||
/**
|
||||
* A drawable resource identifier (in the package's resources) of this
|
||||
* component's logo. Logos may be larger/wider than icons and are
|
||||
* displayed by certain UI elements in place of a name or name/icon
|
||||
* combination. From the "logo" attribute or, if not set, 0.
|
||||
*/
|
||||
public int logo;
|
||||
|
||||
/**
|
||||
* Additional meta-data associated with this component. This field
|
||||
* will only be filled in if you set the
|
||||
* {@link PackageManager#GET_META_DATA} flag when requesting the info.
|
||||
*/
|
||||
public Bundle metaData;
|
||||
/**
|
||||
* If different of UserHandle.USER_NULL, The icon of this item will be the one of that user.
|
||||
* @hide
|
||||
*/
|
||||
public int showUserIcon;
|
||||
public PackageItemInfo() {
|
||||
// showUserIcon = UserHandle.USER_NULL;
|
||||
}
|
||||
public PackageItemInfo(PackageItemInfo orig) {
|
||||
name = orig.name;
|
||||
if (name != null) name = name.trim();
|
||||
packageName = orig.packageName;
|
||||
labelRes = orig.labelRes;
|
||||
nonLocalizedLabel = orig.nonLocalizedLabel;
|
||||
if (nonLocalizedLabel != null) nonLocalizedLabel = nonLocalizedLabel.toString().trim();
|
||||
icon = orig.icon;
|
||||
banner = orig.banner;
|
||||
logo = orig.logo;
|
||||
metaData = orig.metaData;
|
||||
showUserIcon = orig.showUserIcon;
|
||||
}
|
||||
/**
|
||||
* Retrieve the current textual label associated with this item. This
|
||||
* will call back on the given PackageManager to load the label from
|
||||
* the application.
|
||||
*
|
||||
* @param pm A PackageManager from which the label can be loaded; usually
|
||||
* the PackageManager from which you originally retrieved this item.
|
||||
*
|
||||
* @return Returns a CharSequence containing the item's label. If the
|
||||
* item does not have a label, its name is returned.
|
||||
*/
|
||||
public CharSequence loadLabel(PackageManager pm) {
|
||||
if (nonLocalizedLabel != null) {
|
||||
return nonLocalizedLabel;
|
||||
}
|
||||
if (labelRes != 0) {
|
||||
CharSequence label = pm.getText(packageName, labelRes, getApplicationInfo());
|
||||
if (label != null) {
|
||||
return label.toString().trim();
|
||||
}
|
||||
}
|
||||
if (name != null) {
|
||||
return name;
|
||||
}
|
||||
return packageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the current graphical icon associated with this item. This
|
||||
* will call back on the given PackageManager to load the icon from
|
||||
* the application.
|
||||
*
|
||||
* @param pm A PackageManager from which the icon can be loaded; usually
|
||||
* the PackageManager from which you originally retrieved this item.
|
||||
*
|
||||
* @return Returns a Drawable containing the item's icon. If the
|
||||
* item does not have an icon, the item's default icon is returned
|
||||
* such as the default activity icon.
|
||||
*/
|
||||
public Drawable loadIcon(PackageManager pm) {
|
||||
throw new NotImplementedError();
|
||||
}
|
||||
/**
|
||||
* Retrieve the current graphical icon associated with this item without
|
||||
* the addition of a work badge if applicable.
|
||||
* This will call back on the given PackageManager to load the icon from
|
||||
* the application.
|
||||
*
|
||||
* @param pm A PackageManager from which the icon can be loaded; usually
|
||||
* the PackageManager from which you originally retrieved this item.
|
||||
*
|
||||
* @return Returns a Drawable containing the item's icon. If the
|
||||
* item does not have an icon, the item's default icon is returned
|
||||
* such as the default activity icon.
|
||||
*/
|
||||
public Drawable loadUnbadgedIcon(PackageManager pm) {
|
||||
throw new NotImplementedError();
|
||||
}
|
||||
/**
|
||||
* Retrieve the current graphical banner associated with this item. This
|
||||
* will call back on the given PackageManager to load the banner from
|
||||
* the application.
|
||||
*
|
||||
* @param pm A PackageManager from which the banner can be loaded; usually
|
||||
* the PackageManager from which you originally retrieved this item.
|
||||
*
|
||||
* @return Returns a Drawable containing the item's banner. If the item
|
||||
* does not have a banner, this method will return null.
|
||||
*/
|
||||
public Drawable loadBanner(PackageManager pm) {
|
||||
if (banner != 0) {
|
||||
Drawable dr = pm.getDrawable(packageName, banner, getApplicationInfo());
|
||||
if (dr != null) {
|
||||
return dr;
|
||||
}
|
||||
}
|
||||
return loadDefaultBanner(pm);
|
||||
}
|
||||
/**
|
||||
* Retrieve the default graphical icon associated with this item.
|
||||
*
|
||||
* @param pm A PackageManager from which the icon can be loaded; usually
|
||||
* the PackageManager from which you originally retrieved this item.
|
||||
*
|
||||
* @return Returns a Drawable containing the item's default icon
|
||||
* such as the default activity icon.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public Drawable loadDefaultIcon(PackageManager pm) {
|
||||
return pm.getDefaultActivityIcon();
|
||||
}
|
||||
/**
|
||||
* Retrieve the default graphical banner associated with this item.
|
||||
*
|
||||
* @param pm A PackageManager from which the banner can be loaded; usually
|
||||
* the PackageManager from which you originally retrieved this item.
|
||||
*
|
||||
* @return Returns a Drawable containing the item's default banner
|
||||
* or null if no default logo is available.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
protected Drawable loadDefaultBanner(PackageManager pm) {
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Retrieve the current graphical logo associated with this item. This
|
||||
* will call back on the given PackageManager to load the logo from
|
||||
* the application.
|
||||
*
|
||||
* @param pm A PackageManager from which the logo can be loaded; usually
|
||||
* the PackageManager from which you originally retrieved this item.
|
||||
*
|
||||
* @return Returns a Drawable containing the item's logo. If the item
|
||||
* does not have a logo, this method will return null.
|
||||
*/
|
||||
public Drawable loadLogo(PackageManager pm) {
|
||||
if (logo != 0) {
|
||||
Drawable d = pm.getDrawable(packageName, logo, getApplicationInfo());
|
||||
if (d != null) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return loadDefaultLogo(pm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the default graphical logo associated with this item.
|
||||
*
|
||||
* @param pm A PackageManager from which the logo can be loaded; usually
|
||||
* the PackageManager from which you originally retrieved this item.
|
||||
*
|
||||
* @return Returns a Drawable containing the item's default logo
|
||||
* or null if no default logo is available.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
protected Drawable loadDefaultLogo(PackageManager pm) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an XML resource attached to the meta-data of this item. This will
|
||||
* retrieved the name meta-data entry, and if defined call back on the
|
||||
* given PackageManager to load its XML file from the application.
|
||||
*
|
||||
* @param pm A PackageManager from which the XML can be loaded; usually
|
||||
* the PackageManager from which you originally retrieved this item.
|
||||
* @param name Name of the meta-date you would like to load.
|
||||
*
|
||||
* @return Returns an XmlPullParser you can use to parse the XML file
|
||||
* assigned as the given meta-data. If the meta-data name is not defined
|
||||
* or the XML resource could not be found, null is returned.
|
||||
*/
|
||||
public XmlResourceParser loadXmlMetaData(PackageManager pm, String name) {
|
||||
if (metaData != null) {
|
||||
int resid = metaData.getInt(name);
|
||||
if (resid != 0) {
|
||||
return pm.getXml(packageName, resid, getApplicationInfo());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* @hide Flag for dumping: include all details.
|
||||
*/
|
||||
public static final int DUMP_FLAG_DETAILS = 1<<0;
|
||||
/**
|
||||
* @hide Flag for dumping: include nested ApplicationInfo.
|
||||
*/
|
||||
public static final int DUMP_FLAG_APPLICATION = 1<<1;
|
||||
/**
|
||||
* @hide Flag for dumping: all flags to dump everything.
|
||||
*/
|
||||
public static final int DUMP_FLAG_ALL = DUMP_FLAG_DETAILS | DUMP_FLAG_APPLICATION;
|
||||
protected void dumpFront(Printer pw, String prefix) {
|
||||
if (name != null) {
|
||||
pw.println(prefix + "name=" + name);
|
||||
}
|
||||
pw.println(prefix + "packageName=" + packageName);
|
||||
if (labelRes != 0 || nonLocalizedLabel != null || icon != 0 || banner != 0) {
|
||||
pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes)
|
||||
+ " nonLocalizedLabel=" + nonLocalizedLabel
|
||||
+ " icon=0x" + Integer.toHexString(icon)
|
||||
+ " banner=0x" + Integer.toHexString(banner));
|
||||
}
|
||||
}
|
||||
|
||||
protected void dumpBack(Printer pw, String prefix) {
|
||||
// no back here
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel dest, int parcelableFlags) {
|
||||
dest.writeString(name);
|
||||
dest.writeString(packageName);
|
||||
dest.writeInt(labelRes);
|
||||
dest.writeInt(icon);
|
||||
dest.writeInt(logo);
|
||||
dest.writeBundle(metaData);
|
||||
dest.writeInt(banner);
|
||||
dest.writeInt(showUserIcon);
|
||||
}
|
||||
|
||||
protected PackageItemInfo(Parcel source) {
|
||||
name = source.readString();
|
||||
packageName = source.readString();
|
||||
labelRes = source.readInt();
|
||||
icon = source.readInt();
|
||||
logo = source.readInt();
|
||||
metaData = source.readBundle();
|
||||
banner = source.readInt();
|
||||
showUserIcon = source.readInt();
|
||||
}
|
||||
/**
|
||||
* Get the ApplicationInfo for the application to which this item belongs,
|
||||
* if available, otherwise returns null.
|
||||
*
|
||||
* @return Returns the ApplicationInfo of this item, or null if not known.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
protected ApplicationInfo getApplicationInfo() {
|
||||
return null;
|
||||
}
|
||||
public static class DisplayNameComparator
|
||||
implements Comparator<PackageItemInfo> {
|
||||
public DisplayNameComparator(PackageManager pm) {
|
||||
mPM = pm;
|
||||
}
|
||||
public final int compare(PackageItemInfo aa, PackageItemInfo ab) {
|
||||
CharSequence sa = aa.loadLabel(mPM);
|
||||
if (sa == null) sa = aa.name;
|
||||
CharSequence sb = ab.loadLabel(mPM);
|
||||
if (sb == null) sb = ab.name;
|
||||
return sCollator.compare(sa.toString(), sb.toString());
|
||||
}
|
||||
private final Collator sCollator = Collator.getInstance();
|
||||
private PackageManager mPM;
|
||||
}
|
||||
}
|
5318
AndroidCompat/src/main/java/android/content/pm/PackageManager.java
Normal file
5318
AndroidCompat/src/main/java/android/content/pm/PackageManager.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,15 @@
|
||||
package android.content.pm;
|
||||
|
||||
public class PackageParser {
|
||||
public static class PackageParserException extends Exception {
|
||||
public final int error;
|
||||
public PackageParserException(int error, String detailMessage) {
|
||||
super(detailMessage);
|
||||
this.error = error;
|
||||
}
|
||||
public PackageParserException(int error, String detailMessage, Throwable throwable) {
|
||||
super(detailMessage, throwable);
|
||||
this.error = error;
|
||||
}
|
||||
}
|
||||
}
|
178
AndroidCompat/src/main/java/android/content/pm/Signature.java
Normal file
178
AndroidCompat/src/main/java/android/content/pm/Signature.java
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.content.pm;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.util.Arrays;
|
||||
/**
|
||||
* Opaque, immutable representation of a signature associated with an
|
||||
* application package.
|
||||
*/
|
||||
public class Signature implements Parcelable {
|
||||
private final byte[] mSignature;
|
||||
private int mHashCode;
|
||||
private boolean mHaveHashCode;
|
||||
private SoftReference<String> mStringRef;
|
||||
/**
|
||||
* Create Signature from an existing raw byte array.
|
||||
*/
|
||||
public Signature(byte[] signature) {
|
||||
mSignature = signature.clone();
|
||||
}
|
||||
private static final int parseHexDigit(int nibble) {
|
||||
if ('0' <= nibble && nibble <= '9') {
|
||||
return nibble - '0';
|
||||
} else if ('a' <= nibble && nibble <= 'f') {
|
||||
return nibble - 'a' + 10;
|
||||
} else if ('A' <= nibble && nibble <= 'F') {
|
||||
return nibble - 'A' + 10;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid character " + nibble + " in hex string");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Create Signature from a text representation previously returned by
|
||||
* {@link #toChars} or {@link #toCharsString()}. Signatures are expected to
|
||||
* be a hex-encoded ASCII string.
|
||||
*
|
||||
* @param text hex-encoded string representing the signature
|
||||
* @throws IllegalArgumentException when signature is odd-length
|
||||
*/
|
||||
public Signature(String text) {
|
||||
final byte[] input = text.getBytes();
|
||||
final int N = input.length;
|
||||
if (N % 2 != 0) {
|
||||
throw new IllegalArgumentException("text size " + N + " is not even");
|
||||
}
|
||||
final byte[] sig = new byte[N / 2];
|
||||
int sigIndex = 0;
|
||||
for (int i = 0; i < N;) {
|
||||
final int hi = parseHexDigit(input[i++]);
|
||||
final int lo = parseHexDigit(input[i++]);
|
||||
sig[sigIndex++] = (byte) ((hi << 4) | lo);
|
||||
}
|
||||
mSignature = sig;
|
||||
}
|
||||
/**
|
||||
* Encode the Signature as ASCII text.
|
||||
*/
|
||||
public char[] toChars() {
|
||||
return toChars(null, null);
|
||||
}
|
||||
/**
|
||||
* Encode the Signature as ASCII text in to an existing array.
|
||||
*
|
||||
* @param existingArray Existing char array or null.
|
||||
* @param outLen Output parameter for the number of characters written in
|
||||
* to the array.
|
||||
* @return Returns either <var>existingArray</var> if it was large enough
|
||||
* to hold the ASCII representation, or a newly created char[] array if
|
||||
* needed.
|
||||
*/
|
||||
public char[] toChars(char[] existingArray, int[] outLen) {
|
||||
byte[] sig = mSignature;
|
||||
final int N = sig.length;
|
||||
final int N2 = N*2;
|
||||
char[] text = existingArray == null || N2 > existingArray.length
|
||||
? new char[N2] : existingArray;
|
||||
for (int j=0; j<N; j++) {
|
||||
byte v = sig[j];
|
||||
int d = (v>>4)&0xf;
|
||||
text[j*2] = (char)(d >= 10 ? ('a' + d - 10) : ('0' + d));
|
||||
d = v&0xf;
|
||||
text[j*2+1] = (char)(d >= 10 ? ('a' + d - 10) : ('0' + d));
|
||||
}
|
||||
if (outLen != null) outLen[0] = N;
|
||||
return text;
|
||||
}
|
||||
/**
|
||||
* Return the result of {@link #toChars()} as a String.
|
||||
*/
|
||||
public String toCharsString() {
|
||||
String str = mStringRef == null ? null : mStringRef.get();
|
||||
if (str != null) {
|
||||
return str;
|
||||
}
|
||||
str = new String(toChars());
|
||||
mStringRef = new SoftReference<String>(str);
|
||||
return str;
|
||||
}
|
||||
/**
|
||||
* @return the contents of this signature as a byte array.
|
||||
*/
|
||||
public byte[] toByteArray() {
|
||||
byte[] bytes = new byte[mSignature.length];
|
||||
System.arraycopy(mSignature, 0, bytes, 0, mSignature.length);
|
||||
return bytes;
|
||||
}
|
||||
/**
|
||||
* Returns the public key for this signature.
|
||||
*
|
||||
* @throws CertificateException when Signature isn't a valid X.509
|
||||
* certificate; shouldn't happen.
|
||||
* @hide
|
||||
*/
|
||||
public PublicKey getPublicKey() throws CertificateException {
|
||||
final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
|
||||
final ByteArrayInputStream bais = new ByteArrayInputStream(mSignature);
|
||||
final Certificate cert = certFactory.generateCertificate(bais);
|
||||
return cert.getPublicKey();
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
try {
|
||||
if (obj != null) {
|
||||
Signature other = (Signature)obj;
|
||||
return this == other || Arrays.equals(mSignature, other.mSignature);
|
||||
}
|
||||
} catch (ClassCastException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (mHaveHashCode) {
|
||||
return mHashCode;
|
||||
}
|
||||
mHashCode = Arrays.hashCode(mSignature);
|
||||
mHaveHashCode = true;
|
||||
return mHashCode;
|
||||
}
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
public void writeToParcel(Parcel dest, int parcelableFlags) {
|
||||
dest.writeByteArray(mSignature);
|
||||
}
|
||||
public static final Parcelable.Creator<Signature> CREATOR
|
||||
= new Parcelable.Creator<Signature>() {
|
||||
public Signature createFromParcel(Parcel source) {
|
||||
return new Signature(source);
|
||||
}
|
||||
public Signature[] newArray(int size) {
|
||||
return new Signature[size];
|
||||
}
|
||||
};
|
||||
private Signature(Parcel source) {
|
||||
mSignature = source.createByteArray();
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.content.pm;
|
||||
import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
/**
|
||||
* Encapsulates a package and its version code.
|
||||
*/
|
||||
public final class VersionedPackage implements Parcelable {
|
||||
private final String mPackageName;
|
||||
private final int mVersionCode;
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntRange(from = PackageManager.VERSION_CODE_HIGHEST)
|
||||
public @interface VersionCode{}
|
||||
/**
|
||||
* Creates a new instance. Use {@link PackageManager#VERSION_CODE_HIGHEST}
|
||||
* to refer to the highest version code of this package.
|
||||
* @param packageName The package name.
|
||||
* @param versionCode The version code.
|
||||
*/
|
||||
public VersionedPackage(@NonNull String packageName,
|
||||
@VersionCode int versionCode) {
|
||||
mPackageName = packageName;
|
||||
mVersionCode = versionCode;
|
||||
}
|
||||
private VersionedPackage(Parcel parcel) {
|
||||
mPackageName = parcel.readString();
|
||||
mVersionCode = parcel.readInt();
|
||||
}
|
||||
/**
|
||||
* Gets the package name.
|
||||
*
|
||||
* @return The package name.
|
||||
*/
|
||||
public @NonNull String getPackageName() {
|
||||
return mPackageName;
|
||||
}
|
||||
/**
|
||||
* Gets the version code.
|
||||
*
|
||||
* @return The version code.
|
||||
*/
|
||||
public @VersionCode int getVersionCode() {
|
||||
return mVersionCode;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VersionedPackage[" + mPackageName + "/" + mVersionCode + "]";
|
||||
}
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeString(mPackageName);
|
||||
parcel.writeInt(mVersionCode);
|
||||
}
|
||||
public static final Creator<VersionedPackage> CREATOR = new Creator<VersionedPackage>() {
|
||||
@Override
|
||||
public VersionedPackage createFromParcel(Parcel source) {
|
||||
return new VersionedPackage(source);
|
||||
}
|
||||
@Override
|
||||
public VersionedPackage[] newArray(int size) {
|
||||
return new VersionedPackage[size];
|
||||
}
|
||||
};
|
||||
}
|
@ -0,0 +1,296 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.content.res;
|
||||
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
|
||||
/**
|
||||
* CompatibilityInfo class keeps the information about compatibility mode that the application is
|
||||
* running under.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public class CompatibilityInfo implements Parcelable {
|
||||
|
||||
/** default compatibility info object for compatible applications */
|
||||
public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = null;
|
||||
|
||||
/**
|
||||
* This is the number of pixels we would like to have along the
|
||||
* short axis of an app that needs to run on a normal size screen.
|
||||
*/
|
||||
public static final int DEFAULT_NORMAL_SHORT_DIMENSION = 320;
|
||||
|
||||
/**
|
||||
* This is the maximum aspect ratio we will allow while keeping
|
||||
* applications in a compatible screen size.
|
||||
*/
|
||||
public static final float MAXIMUM_ASPECT_RATIO = (854f/480f);
|
||||
|
||||
/**
|
||||
* A compatibility flags
|
||||
*/
|
||||
private final int mCompatibilityFlags;
|
||||
|
||||
/**
|
||||
* A flag mask to tell if the application needs scaling (when mApplicationScale != 1.0f)
|
||||
* {@see compatibilityFlag}
|
||||
*/
|
||||
private static final int SCALING_REQUIRED = 1;
|
||||
|
||||
/**
|
||||
* Application must always run in compatibility mode?
|
||||
*/
|
||||
private static final int ALWAYS_NEEDS_COMPAT = 2;
|
||||
|
||||
/**
|
||||
* Application never should run in compatibility mode?
|
||||
*/
|
||||
private static final int NEVER_NEEDS_COMPAT = 4;
|
||||
|
||||
/**
|
||||
* Set if the application needs to run in screen size compatibility mode.
|
||||
*/
|
||||
private static final int NEEDS_SCREEN_COMPAT = 8;
|
||||
|
||||
/**
|
||||
* The effective screen density we have selected for this application.
|
||||
*/
|
||||
public final int applicationDensity;
|
||||
|
||||
/**
|
||||
* Application's scale.
|
||||
*/
|
||||
public final float applicationScale;
|
||||
|
||||
/**
|
||||
* Application's inverted scale.
|
||||
*/
|
||||
public final float applicationInvertedScale;
|
||||
|
||||
public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw, boolean forceCompat) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
private CompatibilityInfo(int compFlags, int dens, float scale, float invertedScale) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
private CompatibilityInfo() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the scaling is required
|
||||
*/
|
||||
public boolean isScalingRequired() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public boolean supportsScreen() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public boolean neverSupportsScreen() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public boolean alwaysSupportsScreen() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the translator which translates the coordinates in compatibility mode.
|
||||
* @param params the window's parameter
|
||||
*/
|
||||
public Translator getTranslator() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper object to translate the screen and window coordinates back and forth.
|
||||
* @hide
|
||||
*/
|
||||
public class Translator {
|
||||
|
||||
public final float applicationScale;
|
||||
|
||||
public final float applicationInvertedScale;
|
||||
|
||||
private Rect mContentInsetsBuffer = null;
|
||||
|
||||
private Rect mVisibleInsetsBuffer = null;
|
||||
|
||||
private Region mTouchableAreaBuffer = null;
|
||||
|
||||
Translator(float applicationScale, float applicationInvertedScale) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
Translator() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the screen rect to the application frame.
|
||||
*/
|
||||
public void translateRectInScreenToAppWinFrame(Rect rect) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the region in window to screen.
|
||||
*/
|
||||
public void translateRegionInWindowToScreen(Region transparentRegion) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply translation to the canvas that is necessary to draw the content.
|
||||
*/
|
||||
public void translateCanvas(Canvas canvas) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the motion event captured on screen to the application's window.
|
||||
*/
|
||||
public void translateEventInScreenToAppWindow(MotionEvent event) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the window's layout parameter, from application's view to
|
||||
* Screen's view.
|
||||
*/
|
||||
public void translateWindowLayout(WindowManager.LayoutParams params) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a Rect in application's window to screen.
|
||||
*/
|
||||
public void translateRectInAppWindowToScreen(Rect rect) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a Rect in screen coordinates into the app window's coordinates.
|
||||
*/
|
||||
public void translateRectInScreenToAppWindow(Rect rect) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a Point in screen coordinates into the app window's coordinates.
|
||||
*/
|
||||
public void translatePointInScreenToAppWindow(PointF point) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the location of the sub window.
|
||||
* @param params
|
||||
*/
|
||||
public void translateLayoutParamsInAppWindowToScreen(LayoutParams params) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the content insets in application window to Screen. This uses
|
||||
* the internal buffer for content insets to avoid extra object allocation.
|
||||
*/
|
||||
public Rect getTranslatedContentInsets(Rect contentInsets) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the visible insets in application window to Screen. This uses
|
||||
* the internal buffer for visible insets to avoid extra object allocation.
|
||||
*/
|
||||
public Rect getTranslatedVisibleInsets(Rect visibleInsets) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the touchable area in application window to Screen. This uses
|
||||
* the internal buffer for touchable area to avoid extra object allocation.
|
||||
*/
|
||||
public Region getTranslatedTouchableArea(Region touchableArea) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
}
|
||||
|
||||
public void applyToDisplayMetrics(DisplayMetrics inoutDm) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public void applyToConfiguration(int displayDensity, Configuration inoutConfig) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the frame Rect for applications runs under compatibility mode.
|
||||
*
|
||||
* @param dm the display metrics used to compute the frame size.
|
||||
* @param outDm If non-null the width and height will be set to their scaled values.
|
||||
* @return Returns the scaling factor for the window.
|
||||
*/
|
||||
public static float computeCompatibleScaling(DisplayMetrics dm, DisplayMetrics outDm) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<CompatibilityInfo> CREATOR = null;
|
||||
|
||||
private CompatibilityInfo(Parcel source) {
|
||||
throw new RuntimeException("Stub!");
|
||||
}
|
||||
}
|
414
AndroidCompat/src/main/java/android/database/AbstractCursor.java
Normal file
414
AndroidCompat/src/main/java/android/database/AbstractCursor.java
Normal file
@ -0,0 +1,414 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.database;
|
||||
import android.content.ContentResolver;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import kotlin.NotImplementedError;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
/**
|
||||
* This is an abstract cursor class that handles a lot of the common code
|
||||
* that all cursors need to deal with and is provided for convenience reasons.
|
||||
*/
|
||||
public abstract class AbstractCursor implements CrossProcessCursor {
|
||||
private static final String TAG = "Cursor";
|
||||
/**
|
||||
* @removed This field should not be used.
|
||||
*/
|
||||
protected HashMap<Long, Map<String, Object>> mUpdatedRows;
|
||||
/**
|
||||
* @removed This field should not be used.
|
||||
*/
|
||||
protected int mRowIdColumnIndex;
|
||||
/**
|
||||
* @removed This field should not be used.
|
||||
*/
|
||||
protected Long mCurrentRowID;
|
||||
/**
|
||||
* @deprecated Use {@link #getPosition()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
protected int mPos;
|
||||
/**
|
||||
* @deprecated Use {@link #isClosed()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
protected boolean mClosed;
|
||||
/**
|
||||
* @deprecated Do not use.
|
||||
*/
|
||||
@Deprecated
|
||||
protected ContentResolver mContentResolver;
|
||||
private Uri mNotifyUri;
|
||||
private final Object mSelfObserverLock = new Object();
|
||||
private ContentObserver mSelfObserver;
|
||||
private boolean mSelfObserverRegistered;
|
||||
private final DataSetObservable mDataSetObservable = new DataSetObservable();
|
||||
private final ContentObservable mContentObservable = new ContentObservable();
|
||||
private Bundle mExtras = Bundle.EMPTY;
|
||||
/* -------------------------------------------------------- */
|
||||
/* These need to be implemented by subclasses */
|
||||
@Override
|
||||
abstract public int getCount();
|
||||
@Override
|
||||
abstract public String[] getColumnNames();
|
||||
@Override
|
||||
abstract public String getString(int column);
|
||||
@Override
|
||||
abstract public short getShort(int column);
|
||||
@Override
|
||||
abstract public int getInt(int column);
|
||||
@Override
|
||||
abstract public long getLong(int column);
|
||||
@Override
|
||||
abstract public float getFloat(int column);
|
||||
@Override
|
||||
abstract public double getDouble(int column);
|
||||
@Override
|
||||
abstract public boolean isNull(int column);
|
||||
@Override
|
||||
public int getType(int column) {
|
||||
// Reflects the assumption that all commonly used field types (meaning everything
|
||||
// but blobs) are convertible to strings so it should be safe to call
|
||||
// getString to retrieve them.
|
||||
return FIELD_TYPE_STRING;
|
||||
}
|
||||
// TODO implement getBlob in all cursor types
|
||||
@Override
|
||||
public byte[] getBlob(int column) {
|
||||
throw new UnsupportedOperationException("getBlob is not supported");
|
||||
}
|
||||
/* -------------------------------------------------------- */
|
||||
/* Methods that may optionally be implemented by subclasses */
|
||||
/**
|
||||
* If the cursor is backed by a {@link CursorWindow}, returns a pre-filled
|
||||
* window with the contents of the cursor, otherwise null.
|
||||
*
|
||||
* @return The pre-filled window that backs this cursor, or null if none.
|
||||
*/
|
||||
@Override
|
||||
public CursorWindow getWindow() {
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return getColumnNames().length;
|
||||
}
|
||||
@Override
|
||||
public void deactivate() {
|
||||
onDeactivateOrClose();
|
||||
}
|
||||
/** @hide */
|
||||
protected void onDeactivateOrClose() {
|
||||
if (mSelfObserver != null) {
|
||||
mContentResolver.unregisterContentObserver(mSelfObserver);
|
||||
mSelfObserverRegistered = false;
|
||||
}
|
||||
mDataSetObservable.notifyInvalidated();
|
||||
}
|
||||
@Override
|
||||
public boolean requery() {
|
||||
if (mSelfObserver != null && mSelfObserverRegistered == false) {
|
||||
mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);
|
||||
mSelfObserverRegistered = true;
|
||||
}
|
||||
mDataSetObservable.notifyChanged();
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
return mClosed;
|
||||
}
|
||||
@Override
|
||||
public void close() {
|
||||
mClosed = true;
|
||||
mContentObservable.unregisterAll();
|
||||
onDeactivateOrClose();
|
||||
}
|
||||
/**
|
||||
* This function is called every time the cursor is successfully scrolled
|
||||
* to a new position, giving the subclass a chance to update any state it
|
||||
* may have. If it returns false the move function will also do so and the
|
||||
* cursor will scroll to the beforeFirst position.
|
||||
*
|
||||
* @param oldPosition the position that we're moving from
|
||||
* @param newPosition the position that we're moving to
|
||||
* @return true if the move is successful, false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean onMove(int oldPosition, int newPosition) {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
|
||||
// Default implementation, uses getString
|
||||
String result = getString(columnIndex);
|
||||
if (result != null) {
|
||||
char[] data = buffer.data;
|
||||
if (data == null || data.length < result.length()) {
|
||||
buffer.data = result.toCharArray();
|
||||
} else {
|
||||
result.getChars(0, result.length(), data, 0);
|
||||
}
|
||||
buffer.sizeCopied = result.length();
|
||||
} else {
|
||||
buffer.sizeCopied = 0;
|
||||
}
|
||||
}
|
||||
/* -------------------------------------------------------- */
|
||||
/* Implementation */
|
||||
public AbstractCursor() {
|
||||
mPos = -1;
|
||||
}
|
||||
@Override
|
||||
public final int getPosition() {
|
||||
return mPos;
|
||||
}
|
||||
@Override
|
||||
public final boolean moveToPosition(int position) {
|
||||
// Make sure position isn't past the end of the cursor
|
||||
final int count = getCount();
|
||||
if (position >= count) {
|
||||
mPos = count;
|
||||
return false;
|
||||
}
|
||||
// Make sure position isn't before the beginning of the cursor
|
||||
if (position < 0) {
|
||||
mPos = -1;
|
||||
return false;
|
||||
}
|
||||
// Check for no-op moves, and skip the rest of the work for them
|
||||
if (position == mPos) {
|
||||
return true;
|
||||
}
|
||||
boolean result = onMove(mPos, position);
|
||||
if (result == false) {
|
||||
mPos = -1;
|
||||
} else {
|
||||
mPos = position;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public void fillWindow(int position, CursorWindow window) {
|
||||
DatabaseUtils.cursorFillWindow(this, position, window);
|
||||
}
|
||||
@Override
|
||||
public final boolean move(int offset) {
|
||||
return moveToPosition(mPos + offset);
|
||||
}
|
||||
@Override
|
||||
public final boolean moveToFirst() {
|
||||
return moveToPosition(0);
|
||||
}
|
||||
@Override
|
||||
public final boolean moveToLast() {
|
||||
return moveToPosition(getCount() - 1);
|
||||
}
|
||||
@Override
|
||||
public final boolean moveToNext() {
|
||||
return moveToPosition(mPos + 1);
|
||||
}
|
||||
@Override
|
||||
public final boolean moveToPrevious() {
|
||||
return moveToPosition(mPos - 1);
|
||||
}
|
||||
@Override
|
||||
public final boolean isFirst() {
|
||||
return mPos == 0 && getCount() != 0;
|
||||
}
|
||||
@Override
|
||||
public final boolean isLast() {
|
||||
int cnt = getCount();
|
||||
return mPos == (cnt - 1) && cnt != 0;
|
||||
}
|
||||
@Override
|
||||
public final boolean isBeforeFirst() {
|
||||
if (getCount() == 0) {
|
||||
return true;
|
||||
}
|
||||
return mPos == -1;
|
||||
}
|
||||
@Override
|
||||
public final boolean isAfterLast() {
|
||||
if (getCount() == 0) {
|
||||
return true;
|
||||
}
|
||||
return mPos == getCount();
|
||||
}
|
||||
@Override
|
||||
public int getColumnIndex(String columnName) {
|
||||
// Hack according to bug 903852
|
||||
final int periodIndex = columnName.lastIndexOf('.');
|
||||
if (periodIndex != -1) {
|
||||
Exception e = new Exception();
|
||||
Log.e(TAG, "requesting column name with table name -- " + columnName, e);
|
||||
columnName = columnName.substring(periodIndex + 1);
|
||||
}
|
||||
String columnNames[] = getColumnNames();
|
||||
int length = columnNames.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (columnNames[i].equalsIgnoreCase(columnName)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
if (false) {
|
||||
if (getCount() > 0) {
|
||||
Log.w("AbstractCursor", "Unknown column " + columnName);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@Override
|
||||
public int getColumnIndexOrThrow(String columnName) {
|
||||
final int index = getColumnIndex(columnName);
|
||||
if (index < 0) {
|
||||
throw new IllegalArgumentException("column '" + columnName + "' does not exist");
|
||||
}
|
||||
return index;
|
||||
}
|
||||
@Override
|
||||
public String getColumnName(int columnIndex) {
|
||||
return getColumnNames()[columnIndex];
|
||||
}
|
||||
@Override
|
||||
public void registerContentObserver(ContentObserver observer) {
|
||||
mContentObservable.registerObserver(observer);
|
||||
}
|
||||
@Override
|
||||
public void unregisterContentObserver(ContentObserver observer) {
|
||||
// cursor will unregister all observers when it close
|
||||
if (!mClosed) {
|
||||
mContentObservable.unregisterObserver(observer);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void registerDataSetObserver(DataSetObserver observer) {
|
||||
mDataSetObservable.registerObserver(observer);
|
||||
}
|
||||
@Override
|
||||
public void unregisterDataSetObserver(DataSetObserver observer) {
|
||||
mDataSetObservable.unregisterObserver(observer);
|
||||
}
|
||||
/**
|
||||
* Subclasses must call this method when they finish committing updates to notify all
|
||||
* observers.
|
||||
*
|
||||
* @param selfChange
|
||||
*/
|
||||
protected void onChange(boolean selfChange) {
|
||||
synchronized (mSelfObserverLock) {
|
||||
mContentObservable.dispatchChange(selfChange, null);
|
||||
if (mNotifyUri != null && selfChange) {
|
||||
mContentResolver.notifyChange(mNotifyUri, mSelfObserver);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Specifies a content URI to watch for changes.
|
||||
*
|
||||
* @param cr The content resolver from the caller's context.
|
||||
* @param notifyUri The URI to watch for changes. This can be a
|
||||
* specific row URI, or a base URI for a whole class of content.
|
||||
*/
|
||||
@Override
|
||||
public void setNotificationUri(ContentResolver cr, Uri notifyUri) {
|
||||
throw new NotImplementedError("Not implemented!");
|
||||
}
|
||||
@Override
|
||||
public Uri getNotificationUri() {
|
||||
synchronized (mSelfObserverLock) {
|
||||
return mNotifyUri;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean getWantsAllOnMoveCalls() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public void setExtras(Bundle extras) {
|
||||
mExtras = (extras == null) ? Bundle.EMPTY : extras;
|
||||
}
|
||||
@Override
|
||||
public Bundle getExtras() {
|
||||
return mExtras;
|
||||
}
|
||||
@Override
|
||||
public Bundle respond(Bundle extras) {
|
||||
return Bundle.EMPTY;
|
||||
}
|
||||
/**
|
||||
* @deprecated Always returns false since Cursors do not support updating rows
|
||||
*/
|
||||
@Deprecated
|
||||
protected boolean isFieldUpdated(int columnIndex) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* @deprecated Always returns null since Cursors do not support updating rows
|
||||
*/
|
||||
@Deprecated
|
||||
protected Object getUpdatedField(int columnIndex) {
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* This function throws CursorIndexOutOfBoundsException if
|
||||
* the cursor position is out of bounds. Subclass implementations of
|
||||
* the get functions should call this before attempting
|
||||
* to retrieve data.
|
||||
*
|
||||
* @throws CursorIndexOutOfBoundsException
|
||||
*/
|
||||
protected void checkPosition() {
|
||||
if (-1 == mPos || getCount() == mPos) {
|
||||
throw new CursorIndexOutOfBoundsException(mPos, getCount());
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void finalize() {
|
||||
if (mSelfObserver != null && mSelfObserverRegistered == true) {
|
||||
mContentResolver.unregisterContentObserver(mSelfObserver);
|
||||
}
|
||||
try {
|
||||
if (!mClosed) close();
|
||||
} catch(Exception e) { }
|
||||
}
|
||||
/**
|
||||
* Cursors use this class to track changes others make to their URI.
|
||||
*/
|
||||
protected static class SelfContentObserver extends ContentObserver {
|
||||
WeakReference<AbstractCursor> mCursor;
|
||||
public SelfContentObserver(AbstractCursor cursor) {
|
||||
super(null);
|
||||
mCursor = new WeakReference<AbstractCursor>(cursor);
|
||||
}
|
||||
@Override
|
||||
public boolean deliverSelfNotifications() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
AbstractCursor cursor = mCursor.get();
|
||||
if (cursor != null) {
|
||||
cursor.onChange(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.database;
|
||||
|
||||
import xyz.nulldev.androidcompat.db.ScrollableResultSet;
|
||||
|
||||
/**
|
||||
* A base class for Cursors that store their data in {@link CursorWindow}s.
|
||||
* <p>
|
||||
* The cursor owns the cursor window it uses. When the cursor is closed,
|
||||
* its window is also closed. Likewise, when the window used by the cursor is
|
||||
* changed, its old window is closed. This policy of strict ownership ensures
|
||||
* that cursor windows are not leaked.
|
||||
* </p><p>
|
||||
* Subclasses are responsible for filling the cursor window with data during
|
||||
* {@link #onMove(int, int)}, allocating a new cursor window if necessary.
|
||||
* During {@link #requery()}, the existing cursor window should be cleared and
|
||||
* filled with new data.
|
||||
* </p><p>
|
||||
* If the contents of the cursor change or become invalid, the old window must be closed
|
||||
* (because it is owned by the cursor) and set to null.
|
||||
* </p>
|
||||
*/
|
||||
public abstract class AbstractWindowedCursor extends AbstractCursor {
|
||||
/**
|
||||
* The cursor window owned by this cursor.
|
||||
*/
|
||||
protected CursorWindow mWindow;
|
||||
@Override
|
||||
public byte[] getBlob(int columnIndex) {
|
||||
checkPosition();
|
||||
return mWindow.getBlob(mPos, columnIndex);
|
||||
}
|
||||
@Override
|
||||
public String getString(int columnIndex) {
|
||||
checkPosition();
|
||||
return mWindow.getString(mPos, columnIndex);
|
||||
}
|
||||
@Override
|
||||
public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
|
||||
checkPosition();
|
||||
mWindow.copyStringToBuffer(mPos, columnIndex, buffer);
|
||||
}
|
||||
@Override
|
||||
public short getShort(int columnIndex) {
|
||||
checkPosition();
|
||||
return mWindow.getShort(mPos, columnIndex);
|
||||
}
|
||||
@Override
|
||||
public int getInt(int columnIndex) {
|
||||
checkPosition();
|
||||
return mWindow.getInt(mPos, columnIndex);
|
||||
}
|
||||
@Override
|
||||
public long getLong(int columnIndex) {
|
||||
checkPosition();
|
||||
return mWindow.getLong(mPos, columnIndex);
|
||||
}
|
||||
@Override
|
||||
public float getFloat(int columnIndex) {
|
||||
checkPosition();
|
||||
return mWindow.getFloat(mPos, columnIndex);
|
||||
}
|
||||
@Override
|
||||
public double getDouble(int columnIndex) {
|
||||
checkPosition();
|
||||
return mWindow.getDouble(mPos, columnIndex);
|
||||
}
|
||||
@Override
|
||||
public boolean isNull(int columnIndex) {
|
||||
checkPosition();
|
||||
return mWindow.getType(mPos, columnIndex) == Cursor.FIELD_TYPE_NULL;
|
||||
}
|
||||
/**
|
||||
* @deprecated Use {@link #getType}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isBlob(int columnIndex) {
|
||||
return getType(columnIndex) == Cursor.FIELD_TYPE_BLOB;
|
||||
}
|
||||
/**
|
||||
* @deprecated Use {@link #getType}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isString(int columnIndex) {
|
||||
return getType(columnIndex) == Cursor.FIELD_TYPE_STRING;
|
||||
}
|
||||
/**
|
||||
* @deprecated Use {@link #getType}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isLong(int columnIndex) {
|
||||
return getType(columnIndex) == Cursor.FIELD_TYPE_INTEGER;
|
||||
}
|
||||
/**
|
||||
* @deprecated Use {@link #getType}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isFloat(int columnIndex) {
|
||||
return getType(columnIndex) == Cursor.FIELD_TYPE_FLOAT;
|
||||
}
|
||||
@Override
|
||||
public int getType(int columnIndex) {
|
||||
checkPosition();
|
||||
return mWindow.getType(mPos, columnIndex);
|
||||
}
|
||||
@Override
|
||||
protected void checkPosition() {
|
||||
super.checkPosition();
|
||||
|
||||
if (mWindow == null) {
|
||||
throw new StaleDataException("Attempting to access a closed CursorWindow." +
|
||||
"Most probable cause: cursor is deactivated prior to calling this method.");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public CursorWindow getWindow() {
|
||||
return mWindow;
|
||||
}
|
||||
/**
|
||||
* Sets a new cursor window for the cursor to use.
|
||||
* <p>
|
||||
* The cursor takes ownership of the provided cursor window; the cursor window
|
||||
* will be closed when the cursor is closed or when the cursor adopts a new
|
||||
* cursor window.
|
||||
* </p><p>
|
||||
* If the cursor previously had a cursor window, then it is closed when the
|
||||
* new cursor window is assigned.
|
||||
* </p>
|
||||
*
|
||||
* @param window The new cursor window, typically a remote cursor window.
|
||||
*/
|
||||
public void setWindow(CursorWindow window) {
|
||||
if (window != mWindow) {
|
||||
closeWindow();
|
||||
mWindow = window;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns true if the cursor has an associated cursor window.
|
||||
*
|
||||
* @return True if the cursor has an associated cursor window.
|
||||
*/
|
||||
public boolean hasWindow() {
|
||||
return mWindow != null;
|
||||
}
|
||||
/**
|
||||
* Closes the cursor window and sets {@link #mWindow} to null.
|
||||
* @hide
|
||||
*/
|
||||
protected void closeWindow() {
|
||||
if (mWindow != null) {
|
||||
mWindow.close();
|
||||
mWindow = null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* If there is a window, clear it.
|
||||
* Otherwise, creates a new window.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
protected void clearOrCreateWindow(ScrollableResultSet rs) {
|
||||
if (mWindow == null) {
|
||||
mWindow = new CursorWindow(rs);
|
||||
} else {
|
||||
mWindow.clear();
|
||||
}
|
||||
}
|
||||
/** @hide */
|
||||
@Override
|
||||
protected void onDeactivateOrClose() {
|
||||
super.onDeactivateOrClose();
|
||||
closeWindow();
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.database;
|
||||
/**
|
||||
* This is used for {@link Cursor#copyStringToBuffer}
|
||||
*/
|
||||
public final class CharArrayBuffer {
|
||||
public CharArrayBuffer(int size) {
|
||||
data = new char[size];
|
||||
}
|
||||
|
||||
public CharArrayBuffer(char[] buf) {
|
||||
data = buf;
|
||||
}
|
||||
|
||||
public char[] data; // In and out parameter
|
||||
public int sizeCopied; // Out parameter
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.database;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
/**
|
||||
* A specialization of {@link Observable} for {@link ContentObserver}
|
||||
* that provides methods for sending notifications to a list of
|
||||
* {@link ContentObserver} objects.
|
||||
*/
|
||||
public class ContentObservable extends Observable<ContentObserver> {
|
||||
// Even though the generic method defined in Observable would be perfectly
|
||||
// fine on its own, we can't delete this overridden method because it would
|
||||
// potentially break binary compatibility with existing applications.
|
||||
@Override
|
||||
public void registerObserver(ContentObserver observer) {
|
||||
super.registerObserver(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes {@link ContentObserver#dispatchChange(boolean)} on each observer.
|
||||
* <p>
|
||||
* If <code>selfChange</code> is true, only delivers the notification
|
||||
* to the observer if it has indicated that it wants to receive self-change
|
||||
* notifications by implementing {@link ContentObserver#deliverSelfNotifications}
|
||||
* to return true.
|
||||
* </p>
|
||||
*
|
||||
* @param selfChange True if this is a self-change notification.
|
||||
*
|
||||
* @deprecated Use {@link #dispatchChange(boolean, Uri)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public void dispatchChange(boolean selfChange) {
|
||||
dispatchChange(selfChange, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes {@link ContentObserver#dispatchChange(boolean, Uri)} on each observer.
|
||||
* Includes the changed content Uri when available.
|
||||
* <p>
|
||||
* If <code>selfChange</code> is true, only delivers the notification
|
||||
* to the observer if it has indicated that it wants to receive self-change
|
||||
* notifications by implementing {@link ContentObserver#deliverSelfNotifications}
|
||||
* to return true.
|
||||
* </p>
|
||||
*
|
||||
* @param selfChange True if this is a self-change notification.
|
||||
* @param uri The Uri of the changed content, or null if unknown.
|
||||
*/
|
||||
public void dispatchChange(boolean selfChange, Uri uri) {
|
||||
synchronized(mObservers) {
|
||||
for (ContentObserver observer : mObservers) {
|
||||
if (!selfChange || observer.deliverSelfNotifications()) {
|
||||
observer.dispatchChange(selfChange, uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes {@link ContentObserver#onChange} on each observer.
|
||||
*
|
||||
* @param selfChange True if this is a self-change notification.
|
||||
*
|
||||
* @deprecated Use {@link #dispatchChange} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public void notifyChange(boolean selfChange) {
|
||||
synchronized(mObservers) {
|
||||
for (ContentObserver observer : mObservers) {
|
||||
observer.onChange(selfChange, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user