mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
Query to detect exposure of sensitive information from android file intent
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
/** Provides Android sink models related to file creation. */
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
import semmle.code.java.dataflow.ExternalFlow
|
||||
import semmle.code.java.frameworks.android.Android
|
||||
import semmle.code.java.frameworks.android.Intent
|
||||
|
||||
/** A sink representing methods creating a file in Android. */
|
||||
class AndroidFileSink extends DataFlow::Node {
|
||||
AndroidFileSink() { sinkNode(this, "create-file") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The Android class `android.os.AsyncTask` for running tasks off the UI thread to achieve
|
||||
* better user experience.
|
||||
*/
|
||||
class AsyncTask extends RefType {
|
||||
AsyncTask() { this.hasQualifiedName("android.os", "AsyncTask") }
|
||||
}
|
||||
|
||||
/** The `execute` method of Android `AsyncTask`. */
|
||||
class AsyncTaskExecuteMethod extends Method {
|
||||
AsyncTaskExecuteMethod() {
|
||||
this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof AsyncTask and
|
||||
this.getName() = "execute"
|
||||
}
|
||||
|
||||
int getParamIndex() { result = 0 }
|
||||
}
|
||||
|
||||
/** The `executeOnExecutor` method of Android `AsyncTask`. */
|
||||
class AsyncTaskExecuteOnExecutorMethod extends Method {
|
||||
AsyncTaskExecuteOnExecutorMethod() {
|
||||
this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof AsyncTask and
|
||||
this.getName() = "executeOnExecutor"
|
||||
}
|
||||
|
||||
int getParamIndex() { result = 1 }
|
||||
}
|
||||
|
||||
/** The `doInBackground` method of Android `AsyncTask`. */
|
||||
class AsyncTaskRunInBackgroundMethod extends Method {
|
||||
AsyncTaskRunInBackgroundMethod() {
|
||||
this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof AsyncTask and
|
||||
this.getName() = "doInBackground"
|
||||
}
|
||||
}
|
||||
|
||||
/** The service start method of Android context. */
|
||||
class ContextStartServiceMethod extends Method {
|
||||
ContextStartServiceMethod() {
|
||||
this.getName() = ["startService", "startForegroundService"] and
|
||||
this.getDeclaringType().getASupertype*() instanceof TypeContext
|
||||
}
|
||||
}
|
||||
|
||||
/** The `onStartCommand` method of Android service. */
|
||||
class ServiceOnStartCommandMethod extends Method {
|
||||
ServiceOnStartCommandMethod() {
|
||||
this.hasName("onStartCommand") and
|
||||
this.getDeclaringType() instanceof AndroidService
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/** Provides summary models relating to file content inputs of Android. */
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.frameworks.android.Android
|
||||
|
||||
/** The `startActivityForResult` method of Android `Activity`. */
|
||||
class StartActivityForResultMethod extends Method {
|
||||
StartActivityForResultMethod() {
|
||||
this.getDeclaringType().getASupertype*() instanceof AndroidActivity and
|
||||
this.getName() = "startActivityForResult"
|
||||
}
|
||||
}
|
||||
|
||||
/** Android class instance of `GET_CONTENT` intent. */
|
||||
class GetContentIntent extends ClassInstanceExpr {
|
||||
GetContentIntent() {
|
||||
this.getConstructedType().getASupertype*() instanceof TypeIntent and
|
||||
this.getArgument(0).(CompileTimeConstantExpr).getStringValue() =
|
||||
"android.intent.action.GET_CONTENT"
|
||||
or
|
||||
exists(Field f |
|
||||
this.getArgument(0) = f.getAnAccess() and
|
||||
f.hasName("ACTION_GET_CONTENT") and
|
||||
f.getDeclaringType() instanceof TypeIntent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Android intent data model in the new CSV format. */
|
||||
private class AndroidIntentDataModel extends SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"android.content;Intent;true;addCategory;;;Argument[-1];ReturnValue;taint",
|
||||
"android.content;Intent;true;addFlags;;;Argument[-1];ReturnValue;taint",
|
||||
"android.content;Intent;true;createChooser;;;Argument[0];ReturnValue;taint",
|
||||
"android.content;Intent;true;getData;;;Argument[-1];ReturnValue;taint",
|
||||
"android.content;Intent;true;getDataString;;;Argument[-1];ReturnValue;taint",
|
||||
"android.content;Intent;true;getExtras;;;Argument[-1];ReturnValue;taint",
|
||||
"android.content;Intent;true;getIntent;;;Argument[-1];ReturnValue;taint",
|
||||
"android.content;Intent;true;get" +
|
||||
[
|
||||
"ParcelableArray", "ParcelableArrayList", "Parcelable", "Serializable", "StringArray",
|
||||
"StringArrayList", "String"
|
||||
] + "Extra;;;Argument[-1..1];ReturnValue;taint",
|
||||
"android.content;Intent;true;put" +
|
||||
[
|
||||
"", "CharSequenceArrayList", "IntegerArrayList", "ParcelableArrayList",
|
||||
"StringArrayList"
|
||||
] + "Extra;;;Argument[1];Argument[-1];taint",
|
||||
"android.content;Intent;true;putExtras;;;Argument[1];Argument[-1];taint",
|
||||
"android.content;Intent;true;setData;;;Argument[0];ReturnValue;taint",
|
||||
"android.content;Intent;true;setDataAndType;;;Argument[-1];ReturnValue;taint",
|
||||
"android.content;Intent;true;setFlags;;;Argument[-1];ReturnValue;taint",
|
||||
"android.content;Intent;true;setType;;;Argument[-1];ReturnValue;taint",
|
||||
"android.net;Uri;true;getEncodedPath;;;Argument[-1];ReturnValue;taint",
|
||||
"android.net;Uri;true;getEncodedQuery;;;Argument[-1];ReturnValue;taint",
|
||||
"android.net;Uri;true;getLastPathSegment;;;Argument[-1];ReturnValue;taint",
|
||||
"android.net;Uri;true;getPath;;;Argument[-1];ReturnValue;taint",
|
||||
"android.net;Uri;true;getPathSegments;;;Argument[-1];ReturnValue;taint",
|
||||
"android.net;Uri;true;getQuery;;;Argument[-1];ReturnValue;taint",
|
||||
"android.net;Uri;true;getQueryParameter;;;Argument[-1];ReturnValue;taint",
|
||||
"android.net;Uri;true;getQueryParameters;;;Argument[-1];ReturnValue;taint",
|
||||
"android.os;AsyncTask;true;execute;;;Argument[0];ReturnValue;taint",
|
||||
"android.os;AsyncTask;true;doInBackground;;;Argument[0];ReturnValue;taint"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/** Taint configuration for getting content intent. */
|
||||
class GetContentIntentConfig extends TaintTracking::Configuration {
|
||||
GetContentIntentConfig() { this = "GetContentIntentConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node src) {
|
||||
exists(GetContentIntent gi | src.asExpr() = gi)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod() instanceof StartActivityForResultMethod and sink.asExpr() = ma.getArgument(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Android `Intent` input to request file loading. */
|
||||
class AndroidFileIntentInput extends LocalUserInput {
|
||||
MethodAccess ma;
|
||||
|
||||
AndroidFileIntentInput() {
|
||||
this.asExpr() = ma.getArgument(0) and
|
||||
ma.getMethod() instanceof StartActivityForResultMethod and
|
||||
exists(GetContentIntentConfig cc, GetContentIntent gi |
|
||||
cc.hasFlow(DataFlow::exprNode(gi), DataFlow::exprNode(ma.getArgument(0)))
|
||||
)
|
||||
}
|
||||
|
||||
/** The request code identifying a specific intent, which is to be matched in `onActivityResult()`. */
|
||||
int getRequestCode() { result = ma.getArgument(1).(CompileTimeConstantExpr).getIntValue() }
|
||||
}
|
||||
|
||||
/** The `onActivityForResult` method of Android `Activity` */
|
||||
class OnActivityForResultMethod extends Method {
|
||||
OnActivityForResultMethod() {
|
||||
this.getDeclaringType().getASupertype*() instanceof AndroidActivity and
|
||||
this.getName() = "onActivityResult"
|
||||
}
|
||||
}
|
||||
|
||||
/** Input of Android activity result from the same application or another application. */
|
||||
class AndroidActivityResultInput extends DataFlow::Node {
|
||||
OnActivityForResultMethod m;
|
||||
|
||||
AndroidActivityResultInput() { this.asExpr() = m.getParameter(2).getAnAccess() }
|
||||
|
||||
/** The request code matching a specific intent request. */
|
||||
VarAccess getRequestCodeVar() { result = m.getParameter(0).getAnAccess() }
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
public class LoadFileFromAppActivity extends Activity {
|
||||
public static final int REQUEST_CODE__SELECT_CONTENT_FROM_APPS = 99;
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == LoadFileFromAppActivity.REQUEST_CODE__SELECT_CONTENT_FROM_APPS &&
|
||||
resultCode == RESULT_OK) {
|
||||
|
||||
{
|
||||
// BAD: Load file without validation
|
||||
loadOfContentFromApps(data, resultCode);
|
||||
}
|
||||
|
||||
{
|
||||
// GOOD: load file with validation
|
||||
if (!data.getData().getPath().startsWith("/data/data")) {
|
||||
loadOfContentFromApps(data, resultCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadOfContentFromApps(Intent contentIntent, int resultCode) {
|
||||
Uri streamsToUpload = contentIntent.getData();
|
||||
try {
|
||||
RandomAccessFile file = new RandomAccessFile(streamsToUpload.getPath(), "r");
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>The Android API allows to start an activity in another mobile application and receive a result back.
|
||||
When starting an activity to retrieve a file from another application, missing input validation can
|
||||
lead to leaking of sensitive configuration file or user data because the intent is from the application
|
||||
itself that is allowed to access its protected data therefore bypassing the access control.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
When loading file data from an activity of another application, validate that the file path is not its own
|
||||
protected directory, which is a subdirectory of the Android application directory <code>/data/data/</code>.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following examples show the bad situation and the good situation respectively. In bad situation, a
|
||||
file is loaded without path validation. In good situation, a file is loaded with path validation.
|
||||
</p>
|
||||
<sample src="LoadFileFromAppActivity.java" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
Google:
|
||||
<a href="https://developer.android.com/training/basics/intents">Android: Interacting with Other Apps</a>.
|
||||
</li>
|
||||
<li>
|
||||
CVE:
|
||||
<a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-32695">CVE-2021-32695: File Sharing Flow Initiated by a Victim Leaks Sensitive Data to a Malicious App</a>.
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @name Leaking sensitive Android file
|
||||
* @description Getting file intent from user input without path validation could leak arbitrary
|
||||
* Android configuration file and sensitive user data.
|
||||
* @kind path-problem
|
||||
* @id java/sensitive_android_file_leak
|
||||
* @tags security
|
||||
* external/cwe/cwe-200
|
||||
*/
|
||||
|
||||
import java
|
||||
import AndroidFileIntentSink
|
||||
import AndroidFileIntentSource
|
||||
import DataFlow2::PathGraph
|
||||
import semmle.code.java.dataflow.TaintTracking2
|
||||
|
||||
class AndroidFileLeakConfig extends TaintTracking2::Configuration {
|
||||
AndroidFileLeakConfig() { this = "AndroidFileLeakConfig" }
|
||||
|
||||
/** Holds if it is an access to file intent result. */
|
||||
override predicate isSource(DataFlow2::Node src) {
|
||||
exists(
|
||||
AndroidActivityResultInput ai, AndroidFileIntentInput fi, IfStmt ifs, VarAccess intentVar // if (requestCode == REQUEST_CODE__SELECT_CONTENT_FROM_APPS)
|
||||
|
|
||||
ifs.getCondition().getAChildExpr().getAChildExpr().(CompileTimeConstantExpr).getIntValue() =
|
||||
fi.getRequestCode() and
|
||||
ifs.getCondition().getAChildExpr().getAChildExpr() = ai.getRequestCodeVar() and
|
||||
intentVar.getType() instanceof TypeIntent and
|
||||
intentVar.(Argument).getAnEnclosingStmt() = ifs.getThen() and
|
||||
src.asExpr() = intentVar
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if it is a sink of file access in Android. */
|
||||
override predicate isSink(DataFlow2::Node sink) { sink instanceof AndroidFileSink }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow2::Node prev, DataFlow2::Node succ) {
|
||||
exists(MethodAccess aema, AsyncTaskRunInBackgroundMethod arm |
|
||||
// fileAsyncTask.execute(params) will invoke doInBackground(params) of FileAsyncTask
|
||||
aema.getQualifier().getType() = arm.getDeclaringType() and
|
||||
(
|
||||
aema.getMethod() instanceof AsyncTaskExecuteMethod and
|
||||
prev.asExpr() = aema.getArgument(0)
|
||||
or
|
||||
aema.getMethod() instanceof AsyncTaskExecuteOnExecutorMethod and
|
||||
prev.asExpr() = aema.getArgument(1)
|
||||
) and
|
||||
succ.asExpr() = arm.getParameter(0).getAnAccess()
|
||||
)
|
||||
or
|
||||
exists(MethodAccess csma, ServiceOnStartCommandMethod ssm, ClassInstanceExpr ce |
|
||||
csma.getMethod() instanceof ContextStartServiceMethod and
|
||||
ce.getConstructedType() instanceof TypeIntent and // Intent intent = new Intent(context, FileUploader.class);
|
||||
ce.getArgument(1).getType().(ParameterizedType).getTypeArgument(0) = ssm.getDeclaringType() and
|
||||
DataFlow2::localExprFlow(ce, csma.getArgument(0)) and // context.startService(intent);
|
||||
prev.asExpr() = csma.getArgument(0) and
|
||||
succ.asExpr() = ssm.getParameter(0).getAnAccess() // public int onStartCommand(Intent intent, int flags, int startId) {...} in FileUploader
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow2::Node node) {
|
||||
exists(
|
||||
MethodAccess startsWith // "startsWith" path check
|
||||
|
|
||||
startsWith.getMethod().hasName("startsWith") and
|
||||
(
|
||||
DataFlow2::localExprFlow(node.asExpr(), startsWith.getQualifier()) or
|
||||
DataFlow2::localExprFlow(node.asExpr(),
|
||||
startsWith.getQualifier().(MethodAccess).getQualifier())
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow2::PathNode source, DataFlow2::PathNode sink, AndroidFileLeakConfig conf
|
||||
where conf.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "Leaking arbitrary Android file from $@.", source.getNode(),
|
||||
"this user input"
|
||||
@@ -0,0 +1,64 @@
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
public class FileService extends Service {
|
||||
public static String KEY_LOCAL_FILE = "local_file";
|
||||
/**
|
||||
* Service initialization
|
||||
*/
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
String localPath = intent.getStringExtra(KEY_LOCAL_FILE);
|
||||
CopyAndUploadContentUrisTask copyTask = new CopyAndUploadContentUrisTask();
|
||||
|
||||
copyTask.execute(
|
||||
copyTask.makeParamsToExecute(localPath)
|
||||
);
|
||||
return 2;
|
||||
}
|
||||
|
||||
public class CopyAndUploadContentUrisTask extends AsyncTask<Object, Void, String> {
|
||||
public Object[] makeParamsToExecute(
|
||||
String sourceUri
|
||||
) {
|
||||
return new Object[] {
|
||||
sourceUri
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doInBackground(Object[] params) {
|
||||
FileOutputStream outputStream = null;
|
||||
|
||||
try {
|
||||
String[] uris = (String[]) params[1];
|
||||
outputStream = new FileOutputStream(uris[0]);
|
||||
return "success";
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return "failure";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String result) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(Void... values) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class GetFileActivity extends Activity {
|
||||
public static final int REQUEST_CODE__SELECT_CONTENT_FROM_APPS = 99;
|
||||
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(-1);
|
||||
|
||||
Intent action = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE);
|
||||
action.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
|
||||
|
||||
startActivityForResult(
|
||||
Intent.createChooser(action, "Open File From Selected Application"), REQUEST_CODE__SELECT_CONTENT_FROM_APPS
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class LeakFileActivity extends Activity {
|
||||
@Override
|
||||
// BAD: Load file from activity without validation
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == GetFileActivity.REQUEST_CODE__SELECT_CONTENT_FROM_APPS &&
|
||||
resultCode == RESULT_OK) {
|
||||
loadOfContentFromApps(data, resultCode);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadOfContentFromApps(Intent contentIntent, int resultCode) {
|
||||
Uri streamsToUpload = contentIntent.getData();
|
||||
try {
|
||||
RandomAccessFile file = new RandomAccessFile(streamsToUpload.getPath(), "r");
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class LeakFileActivity2 extends Activity {
|
||||
@Override
|
||||
// BAD: Load file in a service without validation
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
Uri localPath = data.getData();
|
||||
|
||||
if (requestCode == GetFileActivity.REQUEST_CODE__SELECT_CONTENT_FROM_APPS &&
|
||||
resultCode == RESULT_OK) {
|
||||
Intent intent = new Intent(this, FileService.class);
|
||||
intent.putExtra(FileService.KEY_LOCAL_FILE, localPath);
|
||||
startService(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class SafeFileActivity extends Activity {
|
||||
@Override
|
||||
// GOOD: Load file from activity with path validation
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == GetFileActivity.REQUEST_CODE__SELECT_CONTENT_FROM_APPS &&
|
||||
resultCode == RESULT_OK) {
|
||||
safeLoadOfContentFromApps(data, resultCode);
|
||||
}
|
||||
}
|
||||
|
||||
private void safeLoadOfContentFromApps(Intent contentIntent, int resultCode) {
|
||||
Uri streamsToUpload = contentIntent.getData();
|
||||
try {
|
||||
if (!streamsToUpload.getPath().startsWith("/data/data")) {
|
||||
RandomAccessFile file = new RandomAccessFile(streamsToUpload.getPath(), "r");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
edges
|
||||
| FileService.java:21:28:21:33 | intent : Intent | FileService.java:21:28:21:64 | getStringExtra(...) : String |
|
||||
| FileService.java:21:28:21:33 | intent : Intent | FileService.java:25:42:25:50 | localPath : String |
|
||||
| FileService.java:21:28:21:64 | getStringExtra(...) : String | FileService.java:25:42:25:50 | localPath : String |
|
||||
| FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | FileService.java:44:44:44:49 | params : Object[] |
|
||||
| FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] |
|
||||
| FileService.java:25:42:25:50 | localPath : String | FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String |
|
||||
| FileService.java:44:33:44:52 | (...)... : Object | FileService.java:45:53:45:59 | ...[...] |
|
||||
| FileService.java:44:44:44:49 | params : Object[] | FileService.java:44:33:44:52 | (...)... : Object |
|
||||
| LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:21:28:21:33 | intent : Intent |
|
||||
| LeakFileActivity.java:14:35:14:38 | data : Intent | LeakFileActivity.java:18:40:18:59 | contentIntent : Intent |
|
||||
| LeakFileActivity.java:18:40:18:59 | contentIntent : Intent | LeakFileActivity.java:19:31:19:43 | contentIntent : Intent |
|
||||
| LeakFileActivity.java:19:31:19:43 | contentIntent : Intent | LeakFileActivity.java:19:31:19:53 | getData(...) : Uri |
|
||||
| LeakFileActivity.java:19:31:19:53 | getData(...) : Uri | LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri |
|
||||
| LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri | LeakFileActivity.java:21:58:21:82 | getPath(...) |
|
||||
nodes
|
||||
| FileService.java:21:28:21:33 | intent : Intent | semmle.label | intent : Intent |
|
||||
| FileService.java:21:28:21:64 | getStringExtra(...) : String | semmle.label | getStringExtra(...) : String |
|
||||
| FileService.java:25:13:25:51 | makeParamsToExecute(...) : Object[] | semmle.label | makeParamsToExecute(...) : Object[] |
|
||||
| FileService.java:25:13:25:51 | makeParamsToExecute(...) [[]] : String | semmle.label | makeParamsToExecute(...) [[]] : String |
|
||||
| FileService.java:25:42:25:50 | localPath : String | semmle.label | localPath : String |
|
||||
| FileService.java:44:33:44:52 | (...)... : Object | semmle.label | (...)... : Object |
|
||||
| FileService.java:44:44:44:49 | params : Object[] | semmle.label | params : Object[] |
|
||||
| FileService.java:45:53:45:59 | ...[...] | semmle.label | ...[...] |
|
||||
| LeakFileActivity2.java:16:26:16:31 | intent : Intent | semmle.label | intent : Intent |
|
||||
| LeakFileActivity.java:14:35:14:38 | data : Intent | semmle.label | data : Intent |
|
||||
| LeakFileActivity.java:18:40:18:59 | contentIntent : Intent | semmle.label | contentIntent : Intent |
|
||||
| LeakFileActivity.java:19:31:19:43 | contentIntent : Intent | semmle.label | contentIntent : Intent |
|
||||
| LeakFileActivity.java:19:31:19:53 | getData(...) : Uri | semmle.label | getData(...) : Uri |
|
||||
| LeakFileActivity.java:21:58:21:72 | streamsToUpload : Uri | semmle.label | streamsToUpload : Uri |
|
||||
| LeakFileActivity.java:21:58:21:82 | getPath(...) | semmle.label | getPath(...) |
|
||||
#select
|
||||
| FileService.java:45:53:45:59 | ...[...] | LeakFileActivity2.java:16:26:16:31 | intent : Intent | FileService.java:45:53:45:59 | ...[...] | Leaking arbitrary Android file from $@. | LeakFileActivity2.java:16:26:16:31 | intent | this user input |
|
||||
| LeakFileActivity.java:21:58:21:82 | getPath(...) | LeakFileActivity.java:14:35:14:38 | data : Intent | LeakFileActivity.java:21:58:21:82 | getPath(...) | Leaking arbitrary Android file from $@. | LeakFileActivity.java:14:35:14:38 | data | this user input |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-200/SensitiveAndroidFileLeak.ql
|
||||
@@ -0,0 +1 @@
|
||||
// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/google-android-9.0.0
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package android.app;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
@@ -675,7 +677,16 @@ import android.view.View;
|
||||
* upload, independent of whether the original activity is paused, stopped, or
|
||||
* finished.
|
||||
*/
|
||||
public class Activity {
|
||||
public class Activity extends ContextWrapper {
|
||||
/** Standard activity result: operation canceled. */
|
||||
public static final int RESULT_CANCELED = 0;
|
||||
|
||||
/** Standard activity result: operation succeeded. */
|
||||
public static final int RESULT_OK = -1;
|
||||
|
||||
/** Start of user-defined activity results. */
|
||||
public static final int RESULT_FIRST_USER = 1;
|
||||
|
||||
/** Return the intent that started this activity. */
|
||||
public Intent getIntent() {
|
||||
return null;
|
||||
@@ -1142,4 +1153,37 @@ public class Activity {
|
||||
*/
|
||||
public void startActivities(Intent[] intents, Bundle options) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an activity you launched exits, giving you the requestCode
|
||||
* you started it with, the resultCode it returned, and any additional
|
||||
* data from it. The <var>resultCode</var> will be
|
||||
* {@link #RESULT_CANCELED} if the activity explicitly returned that,
|
||||
* didn't return any result, or crashed during its operation.
|
||||
*
|
||||
* <p>An activity can never receive a result in the resumed state. You can count on
|
||||
* {@link #onResume} being called after this method, though not necessarily immediately after.
|
||||
* If the activity was resumed, it will be paused and the result will be delivered, followed
|
||||
* by {@link #onResume}. If the activity wasn't in the resumed state, then the result will
|
||||
* be delivered, with {@link #onResume} called sometime later when the activity becomes active
|
||||
* again.
|
||||
*
|
||||
* <p>This method is never invoked if your activity sets
|
||||
* {@link android.R.styleable#AndroidManifestActivity_noHistory noHistory} to
|
||||
* <code>true</code>.
|
||||
*
|
||||
* @param requestCode The integer request code originally supplied to
|
||||
* startActivityForResult(), allowing you to identify who this
|
||||
* result came from.
|
||||
* @param resultCode The integer result code returned by the child activity
|
||||
* through its setResult().
|
||||
* @param data An Intent, which can return result data to the caller
|
||||
* (various data can be attached to Intent "extras").
|
||||
*
|
||||
* @see #startActivityForResult
|
||||
* @see #createPendingResult
|
||||
* @see #setResult(int)
|
||||
*/
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
}
|
||||
}
|
||||
|
||||
344
java/ql/test/stubs/google-android-9.0.0/android/app/Service.java
generated
Normal file
344
java/ql/test/stubs/google-android-9.0.0/android/app/Service.java
generated
Normal file
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* 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.content.Intent;
|
||||
import android.content.ContextWrapper;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
/**
|
||||
* 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) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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.
|
||||
* @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 int onStartCommand(Intent intent, int flags, int startId) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
}
|
||||
}
|
||||
29
java/ql/test/stubs/google-android-9.0.0/android/content/ComponentName.java
generated
Normal file
29
java/ql/test/stubs/google-android-9.0.0/android/content/ComponentName.java
generated
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
}
|
||||
@@ -961,4 +961,91 @@ public abstract class Context {
|
||||
* @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
|
||||
*/
|
||||
public abstract void sendOrderedBroadcast(Intent intent, String receiverPermission);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request that a given application service be started. The Intent
|
||||
* should either contain the complete class name of a specific service
|
||||
* implementation to start, or a specific package name to target. If the
|
||||
* Intent is less specified, it logs a warning about this. In this case any of the
|
||||
* multiple matching services may be used. If this service
|
||||
* is not already running, it will be instantiated and started (creating a
|
||||
* process for it if needed); if it is running then it remains running.
|
||||
*
|
||||
* <p>Every call to this method will result in a corresponding call to
|
||||
* the target service's {@link android.app.Service#onStartCommand} method,
|
||||
* with the <var>intent</var> given here. This provides a convenient way
|
||||
* to submit jobs to a service without having to bind and call on to its
|
||||
* interface.
|
||||
*
|
||||
* <p>Using startService() overrides the default service lifetime that is
|
||||
* managed by {@link #bindService}: it requires the service to remain
|
||||
* running until {@link #stopService} is called, regardless of whether
|
||||
* any clients are connected to it. Note that calls to startService()
|
||||
* do not nest: no matter how many times you call startService(),
|
||||
* a single call to {@link #stopService} will stop it.
|
||||
*
|
||||
* <p>The system attempts to keep running services around as much as
|
||||
* possible. The only time they should be stopped is if the current
|
||||
* foreground application is using so many resources that the service needs
|
||||
* to be killed. If any errors happen in the service's process, it will
|
||||
* automatically be restarted.
|
||||
*
|
||||
* <p>This function will throw {@link SecurityException} if you do not
|
||||
* have permission to start the given service.
|
||||
*
|
||||
* <p class="note"><strong>Note:</strong> Each call to startService()
|
||||
* results in significant work done by the system to manage service
|
||||
* lifecycle surrounding the processing of the intent, which can take
|
||||
* multiple milliseconds of CPU time. Due to this cost, startService()
|
||||
* should not be used for frequent intent delivery to a service, and only
|
||||
* for scheduling significant work. Use {@link #bindService bound services}
|
||||
* for high frequency calls.
|
||||
* </p>
|
||||
*
|
||||
* @param service Identifies the service to be started. The Intent must be
|
||||
* fully explicit (supplying a component name). Additional values
|
||||
* may be included in the Intent extras to supply arguments along with
|
||||
* this specific start call.
|
||||
*
|
||||
* @return If the service is being started or is already running, the
|
||||
* {@link ComponentName} of the actual service that was started is
|
||||
* returned; else if the service does not exist null is returned.
|
||||
*
|
||||
* @throws SecurityException If the caller does not have permission to access the service
|
||||
* or the service can not be found.
|
||||
* @throws IllegalStateException If the application is in a state where the service
|
||||
* can not be started (such as not in the foreground in a state when services are allowed).
|
||||
*
|
||||
* @see #stopService
|
||||
* @see #bindService
|
||||
*/
|
||||
public abstract ComponentName startService(Intent service);
|
||||
|
||||
/**
|
||||
* Similar to {@link #startService(Intent)}, but with an implicit promise that the
|
||||
* Service will call {@link android.app.Service#startForeground(int, android.app.Notification)
|
||||
* startForeground(int, android.app.Notification)} once it begins running. The service is given
|
||||
* an amount of time comparable to the ANR interval to do this, otherwise the system
|
||||
* will automatically stop the service and declare the app ANR.
|
||||
*
|
||||
* <p>Unlike the ordinary {@link #startService(Intent)}, this method can be used
|
||||
* at any time, regardless of whether the app hosting the service is in a foreground
|
||||
* state.
|
||||
*
|
||||
* @param service Identifies the service to be started. The Intent must be
|
||||
* fully explicit (supplying a component name). Additional values
|
||||
* may be included in the Intent extras to supply arguments along with
|
||||
* this specific start call.
|
||||
*
|
||||
* @return If the service is being started or is already running, the
|
||||
* {@link ComponentName} of the actual service that was started is
|
||||
* returned; else if the service does not exist null is returned.
|
||||
*
|
||||
* @throws SecurityException If the caller does not have permission to access the service
|
||||
* or the service can not be found.
|
||||
*
|
||||
* @see #stopService
|
||||
* @see android.app.Service#startForeground(int, android.app.Notification)
|
||||
*/
|
||||
public abstract ComponentName startForegroundService(Intent service);
|
||||
}
|
||||
|
||||
186
java/ql/test/stubs/google-android-9.0.0/android/content/ContextWrapper.java
generated
Normal file
186
java/ql/test/stubs/google-android-9.0.0/android/content/ContextWrapper.java
generated
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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 java.io.File;
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
public ContextWrapper() {
|
||||
}
|
||||
|
||||
public ContextWrapper(Context base) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getApplicationContext() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getFileStreamPath(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SharedPreferences getSharedPreferences(String name, int mode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getSharedPrefsFile(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] fileList() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDataDir() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getFilesDir() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getNoBackupFilesDir() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getExternalFilesDir(String type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File[] getExternalFilesDirs(String type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getObbDir() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File[] getObbDirs() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getCacheDir() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getCodeCacheDir() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getExternalCacheDir() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File[] getExternalCacheDirs() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File[] getExternalMediaDirs() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDir(String name, int mode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @hide **/
|
||||
@Override
|
||||
public File getPreloadsFileCache() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startActivity(Intent intent) {
|
||||
}
|
||||
|
||||
/** @hide **/
|
||||
public void startActivityForResult(
|
||||
String who, Intent intent, int requestCode, Bundle options) {
|
||||
}
|
||||
|
||||
/** @hide **/
|
||||
public boolean canStartActivityForResult() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
|
||||
public void startActivity(Intent intent, Bundle options) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startActivities(Intent[] intents) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startActivities(Intent[] intents, Bundle options) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBroadcast(Intent intent) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBroadcast(Intent intent, String receiverPermission) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBroadcastWithMultiplePermissions(Intent intent, String[] receiverPermissions) {
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOrderedBroadcast(Intent intent,
|
||||
String receiverPermission) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentName startService(Intent service) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentName startForegroundService(Intent service) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -723,6 +723,511 @@ import java.util.Set;
|
||||
*/
|
||||
public class Intent implements Parcelable, Cloneable {
|
||||
|
||||
/**
|
||||
* Activity Action: Start as a main entry point, does not expect to
|
||||
* receive data.
|
||||
* <p>Input: nothing
|
||||
* <p>Output: nothing
|
||||
*/
|
||||
public static final String ACTION_MAIN = "android.intent.action.MAIN";
|
||||
|
||||
/**
|
||||
* Activity Action: Display the data to the user. This is the most common
|
||||
* action performed on data -- it is the generic action you can use on
|
||||
* a piece of data to get the most reasonable thing to occur. For example,
|
||||
* when used on a contacts entry it will view the entry; when used on a
|
||||
* mailto: URI it will bring up a compose window filled with the information
|
||||
* supplied by the URI; when used with a tel: URI it will invoke the
|
||||
* dialer.
|
||||
* <p>Input: {@link #getData} is URI from which to retrieve data.
|
||||
* <p>Output: nothing.
|
||||
*/
|
||||
public static final String ACTION_VIEW = "android.intent.action.VIEW";
|
||||
|
||||
/**
|
||||
* A synonym for {@link #ACTION_VIEW}, the "standard" action that is
|
||||
* performed on a piece of data.
|
||||
*/
|
||||
public static final String ACTION_DEFAULT = ACTION_VIEW;
|
||||
|
||||
/**
|
||||
* Used to indicate that some piece of data should be attached to some other
|
||||
* place. For example, image data could be attached to a contact. It is up
|
||||
* to the recipient to decide where the data should be attached; the intent
|
||||
* does not specify the ultimate destination.
|
||||
* <p>Input: {@link #getData} is URI of data to be attached.
|
||||
* <p>Output: nothing.
|
||||
*/
|
||||
public static final String ACTION_ATTACH_DATA = "android.intent.action.ATTACH_DATA";
|
||||
|
||||
/**
|
||||
* Activity Action: Provide explicit editable access to the given data.
|
||||
* <p>Input: {@link #getData} is URI of data to be edited.
|
||||
* <p>Output: nothing.
|
||||
*/
|
||||
public static final String ACTION_EDIT = "android.intent.action.EDIT";
|
||||
|
||||
/**
|
||||
* Activity Action: Pick an existing item, or insert a new item, and then edit it.
|
||||
* <p>Input: {@link #getType} is the desired MIME type of the item to create or edit.
|
||||
* The extras can contain type specific data to pass through to the editing/creating
|
||||
* activity.
|
||||
* <p>Output: The URI of the item that was picked. This must be a content:
|
||||
* URI so that any receiver can access it.
|
||||
*/
|
||||
public static final String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT";
|
||||
|
||||
/**
|
||||
* Activity Action: Pick an item from the data, returning what was selected.
|
||||
* <p>Input: {@link #getData} is URI containing a directory of data
|
||||
* (vnd.android.cursor.dir/*) from which to pick an item.
|
||||
* <p>Output: The URI of the item that was picked.
|
||||
*/
|
||||
public static final String ACTION_PICK = "android.intent.action.PICK";
|
||||
|
||||
/**
|
||||
* Activity Action: Creates a shortcut.
|
||||
* <p>Input: Nothing.</p>
|
||||
* <p>Output: An Intent representing the shortcut. The intent must contain three
|
||||
* extras: SHORTCUT_INTENT (value: Intent), SHORTCUT_NAME (value: String),
|
||||
* and SHORTCUT_ICON (value: Bitmap) or SHORTCUT_ICON_RESOURCE
|
||||
* (value: ShortcutIconResource).</p>
|
||||
*
|
||||
* @see #EXTRA_SHORTCUT_INTENT
|
||||
* @see #EXTRA_SHORTCUT_NAME
|
||||
* @see #EXTRA_SHORTCUT_ICON
|
||||
* @see #EXTRA_SHORTCUT_ICON_RESOURCE
|
||||
* @see android.content.Intent.ShortcutIconResource
|
||||
*/
|
||||
public static final String ACTION_CREATE_SHORTCUT = "android.intent.action.CREATE_SHORTCUT";
|
||||
|
||||
/**
|
||||
* Activity Action: Display an activity chooser, allowing the user to pick
|
||||
* what they want to before proceeding. This can be used as an alternative
|
||||
* to the standard activity picker that is displayed by the system when
|
||||
* you try to start an activity with multiple possible matches, with these
|
||||
* differences in behavior:
|
||||
* <ul>
|
||||
* <li>You can specify the title that will appear in the activity chooser.
|
||||
* <li>The user does not have the option to make one of the matching
|
||||
* activities a preferred activity, and all possible activities will
|
||||
* always be shown even if one of them is currently marked as the
|
||||
* preferred activity.
|
||||
* </ul>
|
||||
* <p>
|
||||
* This action should be used when the user will naturally expect to
|
||||
* select an activity in order to proceed. An example if when not to use
|
||||
* it is when the user clicks on a "mailto:" link. They would naturally
|
||||
* expect to go directly to their mail app, so startActivity() should be
|
||||
* called directly: it will
|
||||
* either launch the current preferred app, or put up a dialog allowing the
|
||||
* user to pick an app to use and optionally marking that as preferred.
|
||||
* <p>
|
||||
* In contrast, if the user is selecting a menu item to send a picture
|
||||
* they are viewing to someone else, there are many different things they
|
||||
* may want to do at this point: send it through e-mail, upload it to a
|
||||
* web service, etc. In this case the CHOOSER action should be used, to
|
||||
* always present to the user a list of the things they can do, with a
|
||||
* nice title given by the caller such as "Send this photo with:".
|
||||
* <p>
|
||||
* As a convenience, an Intent of this form can be created with the
|
||||
* {@link #createChooser} function.
|
||||
* <p>Input: No data should be specified. get*Extra must have
|
||||
* a {@link #EXTRA_INTENT} field containing the Intent being executed,
|
||||
* and can optionally have a {@link #EXTRA_TITLE} field containing the
|
||||
* title text to display in the chooser.
|
||||
* <p>Output: Depends on the protocol of {@link #EXTRA_INTENT}.
|
||||
*/
|
||||
public static final String ACTION_CHOOSER = "android.intent.action.CHOOSER";
|
||||
|
||||
/**
|
||||
* Convenience function for creating a {@link #ACTION_CHOOSER} Intent.
|
||||
*
|
||||
* @param target The Intent that the user will be selecting an activity
|
||||
* to perform.
|
||||
* @param title Optional title that will be displayed in the chooser.
|
||||
* @return Return a new Intent object that you can hand to
|
||||
* {@link Context#startActivity(Intent) Context.startActivity()} and
|
||||
* related methods.
|
||||
*/
|
||||
public static Intent createChooser(Intent target, CharSequence title) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activity Action: Allow the user to select a particular kind of data and
|
||||
* return it. This is different than {@link #ACTION_PICK} in that here we
|
||||
* just say what kind of data is desired, not a URI of existing data from
|
||||
* which the user can pick. A ACTION_GET_CONTENT could allow the user to
|
||||
* create the data as it runs (for example taking a picture or recording a
|
||||
* sound), let them browse over the web and download the desired data,
|
||||
* etc.
|
||||
* <p>
|
||||
* There are two main ways to use this action: if you want a specific kind
|
||||
* of data, such as a person contact, you set the MIME type to the kind of
|
||||
* data you want and launch it with {@link Context#startActivity(Intent)}.
|
||||
* The system will then launch the best application to select that kind
|
||||
* of data for you.
|
||||
* <p>
|
||||
* You may also be interested in any of a set of types of content the user
|
||||
* can pick. For example, an e-mail application that wants to allow the
|
||||
* user to add an attachment to an e-mail message can use this action to
|
||||
* bring up a list of all of the types of content the user can attach.
|
||||
* <p>
|
||||
* In this case, you should wrap the GET_CONTENT intent with a chooser
|
||||
* (through {@link #createChooser}), which will give the proper interface
|
||||
* for the user to pick how to send your data and allow you to specify
|
||||
* a prompt indicating what they are doing. You will usually specify a
|
||||
* broad MIME type (such as image/* or {@literal *}/*), resulting in a
|
||||
* broad range of content types the user can select from.
|
||||
* <p>
|
||||
* When using such a broad GET_CONTENT action, it is often desirable to
|
||||
* only pick from data that can be represented as a stream. This is
|
||||
* accomplished by requiring the {@link #CATEGORY_OPENABLE} in the Intent.
|
||||
* <p>
|
||||
* Callers can optionally specify {@link #EXTRA_LOCAL_ONLY} to request that
|
||||
* the launched content chooser only returns results representing data that
|
||||
* is locally available on the device. For example, if this extra is set
|
||||
* to true then an image picker should not show any pictures that are available
|
||||
* from a remote server but not already on the local device (thus requiring
|
||||
* they be downloaded when opened).
|
||||
* <p>
|
||||
* Input: {@link #getType} is the desired MIME type to retrieve. Note
|
||||
* that no URI is supplied in the intent, as there are no constraints on
|
||||
* where the returned data originally comes from. You may also include the
|
||||
* {@link #CATEGORY_OPENABLE} if you can only accept data that can be
|
||||
* opened as a stream. You may use {@link #EXTRA_LOCAL_ONLY} to limit content
|
||||
* selection to local data.
|
||||
* <p>
|
||||
* Output: The URI of the item that was picked. This must be a content:
|
||||
* URI so that any receiver can access it.
|
||||
*/
|
||||
public static final String ACTION_GET_CONTENT = "android.intent.action.GET_CONTENT";
|
||||
|
||||
/**
|
||||
* Activity Action: Dial a number as specified by the data. This shows a
|
||||
* UI with the number being dialed, allowing the user to explicitly
|
||||
* initiate the call.
|
||||
* <p>Input: If nothing, an empty dialer is started; else {@link #getData}
|
||||
* is URI of a phone number to be dialed or a tel: URI of an explicit phone
|
||||
* number.
|
||||
* <p>Output: nothing.
|
||||
*/
|
||||
public static final String ACTION_DIAL = "android.intent.action.DIAL";
|
||||
|
||||
/**
|
||||
* Activity Action: Perform a call to someone specified by the data.
|
||||
* <p>Input: If nothing, an empty dialer is started; else {@link #getData}
|
||||
* is URI of a phone number to be dialed or a tel: URI of an explicit phone
|
||||
* number.
|
||||
* <p>Output: nothing.
|
||||
*
|
||||
* <p>Note: there will be restrictions on which applications can initiate a
|
||||
* call; most applications should use the {@link #ACTION_DIAL}.
|
||||
* <p>Note: this Intent <strong>cannot</strong> be used to call emergency
|
||||
* numbers. Applications can <strong>dial</strong> emergency numbers using
|
||||
* {@link #ACTION_DIAL}, however.
|
||||
*/
|
||||
public static final String ACTION_CALL = "android.intent.action.CALL";
|
||||
|
||||
/**
|
||||
* Activity Action: Perform a call to an emergency number specified by the
|
||||
* data.
|
||||
* <p>Input: {@link #getData} is URI of a phone number to be dialed or a
|
||||
* tel: URI of an explicit phone number.
|
||||
* <p>Output: nothing.
|
||||
* @hide
|
||||
*/
|
||||
public static final String ACTION_CALL_EMERGENCY = "android.intent.action.CALL_EMERGENCY";
|
||||
|
||||
/**
|
||||
* Activity action: Perform a call to any number (emergency or not)
|
||||
* specified by the data.
|
||||
* <p>Input: {@link #getData} is URI of a phone number to be dialed or a
|
||||
* tel: URI of an explicit phone number.
|
||||
* <p>Output: nothing.
|
||||
* @hide
|
||||
*/
|
||||
public static final String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED";
|
||||
|
||||
/**
|
||||
* Activity Action: Send a message to someone specified by the data.
|
||||
* <p>Input: {@link #getData} is URI describing the target.
|
||||
* <p>Output: nothing.
|
||||
*/
|
||||
public static final String ACTION_SENDTO = "android.intent.action.SENDTO";
|
||||
|
||||
/**
|
||||
* Activity Action: Deliver some data to someone else. Who the data is
|
||||
* being delivered to is not specified; it is up to the receiver of this
|
||||
* action to ask the user where the data should be sent.
|
||||
* <p>
|
||||
* When launching a SEND intent, you should usually wrap it in a chooser
|
||||
* (through {@link #createChooser}), which will give the proper interface
|
||||
* for the user to pick how to send your data and allow you to specify
|
||||
* a prompt indicating what they are doing.
|
||||
* <p>
|
||||
* Input: {@link #getType} is the MIME type of the data being sent.
|
||||
* get*Extra can have either a {@link #EXTRA_TEXT}
|
||||
* or {@link #EXTRA_STREAM} field, containing the data to be sent. If
|
||||
* using EXTRA_TEXT, the MIME type should be "text/plain"; otherwise it
|
||||
* should be the MIME type of the data in EXTRA_STREAM. Use {@literal *}/*
|
||||
* if the MIME type is unknown (this will only allow senders that can
|
||||
* handle generic data streams).
|
||||
* <p>
|
||||
* Optional standard extras, which may be interpreted by some recipients as
|
||||
* appropriate, are: {@link #EXTRA_EMAIL}, {@link #EXTRA_CC},
|
||||
* {@link #EXTRA_BCC}, {@link #EXTRA_SUBJECT}.
|
||||
* <p>
|
||||
* Output: nothing.
|
||||
*/
|
||||
public static final String ACTION_SEND = "android.intent.action.SEND";
|
||||
|
||||
/**
|
||||
* Activity Action: Deliver multiple data to someone else.
|
||||
* <p>
|
||||
* Like ACTION_SEND, except the data is multiple.
|
||||
* <p>
|
||||
* Input: {@link #getType} is the MIME type of the data being sent.
|
||||
* get*ArrayListExtra can have either a {@link #EXTRA_TEXT} or {@link
|
||||
* #EXTRA_STREAM} field, containing the data to be sent.
|
||||
* <p>
|
||||
* Multiple types are supported, and receivers should handle mixed types
|
||||
* whenever possible. The right way for the receiver to check them is to
|
||||
* use the content resolver on each URI. The intent sender should try to
|
||||
* put the most concrete mime type in the intent type, but it can fall
|
||||
* back to {@literal <type>/*} or {@literal *}/* as needed.
|
||||
* <p>
|
||||
* e.g. if you are sending image/jpg and image/jpg, the intent's type can
|
||||
* be image/jpg, but if you are sending image/jpg and image/png, then the
|
||||
* intent's type should be image/*.
|
||||
* <p>
|
||||
* Optional standard extras, which may be interpreted by some recipients as
|
||||
* appropriate, are: {@link #EXTRA_EMAIL}, {@link #EXTRA_CC},
|
||||
* {@link #EXTRA_BCC}, {@link #EXTRA_SUBJECT}.
|
||||
* <p>
|
||||
* Output: nothing.
|
||||
*/
|
||||
public static final String ACTION_SEND_MULTIPLE = "android.intent.action.SEND_MULTIPLE";
|
||||
|
||||
/**
|
||||
* Activity Action: Handle an incoming phone call.
|
||||
* <p>Input: nothing.
|
||||
* <p>Output: nothing.
|
||||
*/
|
||||
public static final String ACTION_ANSWER = "android.intent.action.ANSWER";
|
||||
|
||||
/**
|
||||
* Activity Action: Insert an empty item into the given container.
|
||||
* <p>Input: {@link #getData} is URI of the directory (vnd.android.cursor.dir/*)
|
||||
* in which to place the data.
|
||||
* <p>Output: URI of the new data that was created.
|
||||
*/
|
||||
public static final String ACTION_INSERT = "android.intent.action.INSERT";
|
||||
|
||||
/**
|
||||
* Activity Action: Create a new item in the given container, initializing it
|
||||
* from the current contents of the clipboard.
|
||||
* <p>Input: {@link #getData} is URI of the directory (vnd.android.cursor.dir/*)
|
||||
* in which to place the data.
|
||||
* <p>Output: URI of the new data that was created.
|
||||
*/
|
||||
public static final String ACTION_PASTE = "android.intent.action.PASTE";
|
||||
|
||||
/**
|
||||
* Activity Action: Delete the given data from its container.
|
||||
* <p>Input: {@link #getData} is URI of data to be deleted.
|
||||
* <p>Output: nothing.
|
||||
*/
|
||||
public static final String ACTION_DELETE = "android.intent.action.DELETE";
|
||||
/**
|
||||
* Activity Action: Run the data, whatever that means.
|
||||
* <p>Input: ? (Note: this is currently specific to the test harness.)
|
||||
* <p>Output: nothing.
|
||||
*/
|
||||
public static final String ACTION_RUN = "android.intent.action.RUN";
|
||||
|
||||
/**
|
||||
* Activity Action: Perform a data synchronization.
|
||||
* <p>Input: ?
|
||||
* <p>Output: ?
|
||||
*/
|
||||
public static final String ACTION_SYNC = "android.intent.action.SYNC";
|
||||
|
||||
/**
|
||||
* Activity Action: Pick an activity given an intent, returning the class
|
||||
* selected.
|
||||
* <p>Input: get*Extra field {@link #EXTRA_INTENT} is an Intent
|
||||
* used with {@link PackageManager#queryIntentActivities} to determine the
|
||||
* set of activities from which to pick.
|
||||
* <p>Output: Class name of the activity that was selected.
|
||||
*/
|
||||
public static final String ACTION_PICK_ACTIVITY = "android.intent.action.PICK_ACTIVITY";
|
||||
|
||||
/**
|
||||
* Activity Action: Perform a search.
|
||||
* <p>Input: {@link android.app.SearchManager#QUERY getStringExtra(SearchManager.QUERY)}
|
||||
* is the text to search for. If empty, simply
|
||||
* enter your search results Activity with the search UI activated.
|
||||
* <p>Output: nothing.
|
||||
*/
|
||||
public static final String ACTION_SEARCH = "android.intent.action.SEARCH";
|
||||
|
||||
/**
|
||||
* Activity Action: Start the platform-defined tutorial
|
||||
* <p>Input: {@link android.app.SearchManager#QUERY getStringExtra(SearchManager.QUERY)}
|
||||
* is the text to search for. If empty, simply
|
||||
* enter your search results Activity with the search UI activated.
|
||||
* <p>Output: nothing.
|
||||
*/
|
||||
public static final String ACTION_SYSTEM_TUTORIAL = "android.intent.action.SYSTEM_TUTORIAL";
|
||||
|
||||
/**
|
||||
* Activity Action: Perform a web search.
|
||||
* <p>
|
||||
* Input: {@link android.app.SearchManager#QUERY
|
||||
* getStringExtra(SearchManager.QUERY)} is the text to search for. If it is
|
||||
* a url starts with http or https, the site will be opened. If it is plain
|
||||
* text, Google search will be applied.
|
||||
* <p>
|
||||
* Output: nothing.
|
||||
*/
|
||||
public static final String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";
|
||||
|
||||
/**
|
||||
* Activity Action: List all available applications
|
||||
* <p>Input: Nothing.
|
||||
* <p>Output: nothing.
|
||||
*/
|
||||
public static final String ACTION_ALL_APPS = "android.intent.action.ALL_APPS";
|
||||
|
||||
/**
|
||||
* Activity Action: Show settings for choosing wallpaper
|
||||
* <p>Input: Nothing.
|
||||
* <p>Output: Nothing.
|
||||
*/
|
||||
public static final String ACTION_SET_WALLPAPER = "android.intent.action.SET_WALLPAPER";
|
||||
|
||||
/**
|
||||
* Activity Action: Show activity for reporting a bug.
|
||||
* <p>Input: Nothing.
|
||||
* <p>Output: Nothing.
|
||||
*/
|
||||
public static final String ACTION_BUG_REPORT = "android.intent.action.BUG_REPORT";
|
||||
|
||||
/**
|
||||
* Activity Action: Main entry point for factory tests. Only used when
|
||||
* the device is booting in factory test node. The implementing package
|
||||
* must be installed in the system image.
|
||||
* <p>Input: nothing
|
||||
* <p>Output: nothing
|
||||
*/
|
||||
public static final String ACTION_FACTORY_TEST = "android.intent.action.FACTORY_TEST";
|
||||
|
||||
/**
|
||||
* Activity Action: The user pressed the "call" button to go to the dialer
|
||||
* or other appropriate UI for placing a call.
|
||||
* <p>Input: Nothing.
|
||||
* <p>Output: Nothing.
|
||||
*/
|
||||
public static final String ACTION_CALL_BUTTON = "android.intent.action.CALL_BUTTON";
|
||||
|
||||
/**
|
||||
* Activity Action: Start Voice Command.
|
||||
* <p>Input: Nothing.
|
||||
* <p>Output: Nothing.
|
||||
*/
|
||||
public static final String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND";
|
||||
|
||||
/**
|
||||
* Activity Action: Start action associated with long pressing on the
|
||||
* search key.
|
||||
* <p>Input: Nothing.
|
||||
* <p>Output: Nothing.
|
||||
*/
|
||||
public static final String ACTION_SEARCH_LONG_PRESS = "android.intent.action.SEARCH_LONG_PRESS";
|
||||
|
||||
/**
|
||||
* Activity Action: The user pressed the "Report" button in the crash/ANR dialog.
|
||||
* This intent is delivered to the package which installed the application, usually
|
||||
* Google Play.
|
||||
* <p>Input: No data is specified. The bug report is passed in using
|
||||
* an {@link #EXTRA_BUG_REPORT} field.
|
||||
* <p>Output: Nothing.
|
||||
*
|
||||
* @see #EXTRA_BUG_REPORT
|
||||
*/
|
||||
public static final String ACTION_APP_ERROR = "android.intent.action.APP_ERROR";
|
||||
|
||||
/**
|
||||
* Activity Action: Show power usage information to the user.
|
||||
* <p>Input: Nothing.
|
||||
* <p>Output: Nothing.
|
||||
*/
|
||||
public static final String ACTION_POWER_USAGE_SUMMARY = "android.intent.action.POWER_USAGE_SUMMARY";
|
||||
|
||||
/**
|
||||
* Activity Action: Setup wizard to launch after a platform update. This
|
||||
* activity should have a string meta-data field associated with it,
|
||||
* {@link #METADATA_SETUP_VERSION}, which defines the current version of
|
||||
* the platform for setup. The activity will be launched only if
|
||||
* {@link android.provider.Settings.Secure#LAST_SETUP_SHOWN} is not the
|
||||
* same value.
|
||||
* <p>Input: Nothing.
|
||||
* <p>Output: Nothing.
|
||||
* @hide
|
||||
*/
|
||||
public static final String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP";
|
||||
|
||||
/**
|
||||
* Activity Action: Show settings for managing network data usage of a
|
||||
* specific application. Applications should define an activity that offers
|
||||
* options to control data usage.
|
||||
*/
|
||||
public static final String ACTION_MANAGE_NETWORK_USAGE =
|
||||
"android.intent.action.MANAGE_NETWORK_USAGE";
|
||||
|
||||
/**
|
||||
* Activity Action: Launch application installer.
|
||||
* <p>
|
||||
* Input: The data must be a content: or file: URI at which the application
|
||||
* can be retrieved. You can optionally supply
|
||||
* {@link #EXTRA_INSTALLER_PACKAGE_NAME}, {@link #EXTRA_NOT_UNKNOWN_SOURCE},
|
||||
* {@link #EXTRA_ALLOW_REPLACE}, and {@link #EXTRA_RETURN_RESULT}.
|
||||
* <p>
|
||||
* Output: If {@link #EXTRA_RETURN_RESULT}, returns whether the install
|
||||
* succeeded.
|
||||
*
|
||||
* @see #EXTRA_INSTALLER_PACKAGE_NAME
|
||||
* @see #EXTRA_NOT_UNKNOWN_SOURCE
|
||||
* @see #EXTRA_RETURN_RESULT
|
||||
*/
|
||||
public static final String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
|
||||
|
||||
/**
|
||||
* Used as a boolean extra field with {@link #ACTION_INSTALL_PACKAGE} to install a
|
||||
* package. Tells the installer UI to skip the confirmation with the user
|
||||
* if the .apk is replacing an existing one.
|
||||
*/
|
||||
public static final String EXTRA_ALLOW_REPLACE
|
||||
= "android.intent.extra.ALLOW_REPLACE";
|
||||
|
||||
/**
|
||||
* Extra used to indicate that an intent can allow the user to select and return multiple items.
|
||||
* This is a boolean extra; the default is false. If true, an implementation is allowed to present
|
||||
* the user with a UI where they can pick multiple items that are all returned to the caller.
|
||||
* When this happens, they should be returned as the getClipData() part of the result Intent.
|
||||
*/
|
||||
public static final String EXTRA_ALLOW_MULTIPLE
|
||||
= "android.intent.extra.ALLOW_MULTIPLE";
|
||||
|
||||
/**
|
||||
* Used to indicate that a GET_CONTENT intent only wants URIs that can be opened with
|
||||
* ContentResolver.openInputStream. Openable URIs must support the columns in OpenableColumns
|
||||
* when queried, though it is allowable for those columns to be blank.
|
||||
*/
|
||||
public static final String CATEGORY_OPENABLE = "android.intent.category.OPENABLE";
|
||||
|
||||
/**
|
||||
* Create an empty intent.
|
||||
*/
|
||||
@@ -1407,6 +1912,35 @@ public class Intent implements Parcelable, Cloneable {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an explicit MIME data type.
|
||||
*
|
||||
* <p>This is used to create intents that only specify a type and not data,
|
||||
* for example to indicate the type of data to return.
|
||||
*
|
||||
* <p>This method automatically clears any data that was
|
||||
* previously set (for example by {@link #setData}).
|
||||
*
|
||||
* <p><em>Note: MIME type matching in the Android framework is
|
||||
* case-sensitive, unlike formal RFC MIME types. As a result,
|
||||
* you should always write your MIME types with lower case letters,
|
||||
* or use {@link #normalizeMimeType} or {@link #setTypeAndNormalize}
|
||||
* to ensure that it is converted to lower case.</em>
|
||||
*
|
||||
* @param type The MIME type of the data being handled by this intent.
|
||||
*
|
||||
* @return Returns the same Intent object, for chaining multiple calls
|
||||
* into a single statement.
|
||||
*
|
||||
* @see #getType
|
||||
* @see #setTypeAndNormalize
|
||||
* @see #setDataAndType
|
||||
* @see #normalizeMimeType
|
||||
*/
|
||||
public Intent setType(String type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add extended data to the intent. The name must include a package prefix, for
|
||||
* example the app com.android.contacts would use names like
|
||||
@@ -2071,4 +2605,23 @@ public class Intent implements Parcelable, Cloneable {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new category to the intent. Categories provide additional detail
|
||||
* about the action the intent performs. When resolving an intent, only
|
||||
* activities that provide <em>all</em> of the requested categories will be
|
||||
* used.
|
||||
*
|
||||
* @param category The desired category. This can be either one of the
|
||||
* predefined Intent categories, or a custom category in your own
|
||||
* namespace.
|
||||
*
|
||||
* @return Returns the same Intent object, for chaining multiple calls
|
||||
* into a single statement.
|
||||
*
|
||||
* @see #hasCategory
|
||||
* @see #removeCategory
|
||||
*/
|
||||
public Intent addCategory(String category) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
406
java/ql/test/stubs/google-android-9.0.0/android/os/AsyncTask.java
generated
Normal file
406
java/ql/test/stubs/google-android-9.0.0/android/os/AsyncTask.java
generated
Normal file
@@ -0,0 +1,406 @@
|
||||
/*
|
||||
* 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.os;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* <p>AsyncTask enables proper and easy use of the UI thread. This class allows you
|
||||
* to perform background operations and publish results on the UI thread without
|
||||
* having to manipulate threads and/or handlers.</p>
|
||||
*
|
||||
* <p>AsyncTask is designed to be a helper class around {@link Thread} and {@link Handler}
|
||||
* and does not constitute a generic threading framework. AsyncTasks should ideally be
|
||||
* used for short operations (a few seconds at the most.) If you need to keep threads
|
||||
* running for long periods of time, it is highly recommended you use the various APIs
|
||||
* provided by the <code>java.util.concurrent</code> package such as {@link Executor},
|
||||
* {@link ThreadPoolExecutor} and {@link FutureTask}.</p>
|
||||
*
|
||||
* <p>An asynchronous task is defined by a computation that runs on a background thread and
|
||||
* whose result is published on the UI thread. An asynchronous task is defined by 3 generic
|
||||
* types, called <code>Params</code>, <code>Progress</code> and <code>Result</code>,
|
||||
* and 4 steps, called <code>onPreExecute</code>, <code>doInBackground</code>,
|
||||
* <code>onProgressUpdate</code> and <code>onPostExecute</code>.</p>
|
||||
*
|
||||
* <div class="special reference">
|
||||
* <h3>Developer Guides</h3>
|
||||
* <p>For more information about using tasks and threads, read the
|
||||
* <a href="{@docRoot}guide/components/processes-and-threads.html">Processes and
|
||||
* Threads</a> developer guide.</p>
|
||||
* </div>
|
||||
*
|
||||
* <h2>Usage</h2>
|
||||
* <p>AsyncTask must be subclassed to be used. The subclass will override at least
|
||||
* one method ({@link #doInBackground}), and most often will override a
|
||||
* second one ({@link #onPostExecute}.)</p>
|
||||
*
|
||||
* <p>Here is an example of subclassing:</p>
|
||||
* <pre class="prettyprint">
|
||||
* private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
|
||||
* protected Long doInBackground(URL... urls) {
|
||||
* int count = urls.length;
|
||||
* long totalSize = 0;
|
||||
* for (int i = 0; i < count; i++) {
|
||||
* totalSize += Downloader.downloadFile(urls[i]);
|
||||
* publishProgress((int) ((i / (float) count) * 100));
|
||||
* // Escape early if cancel() is called
|
||||
* if (isCancelled()) break;
|
||||
* }
|
||||
* return totalSize;
|
||||
* }
|
||||
*
|
||||
* protected void onProgressUpdate(Integer... progress) {
|
||||
* setProgressPercent(progress[0]);
|
||||
* }
|
||||
*
|
||||
* protected void onPostExecute(Long result) {
|
||||
* showDialog("Downloaded " + result + " bytes");
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>Once created, a task is executed very simply:</p>
|
||||
* <pre class="prettyprint">
|
||||
* new DownloadFilesTask().execute(url1, url2, url3);
|
||||
* </pre>
|
||||
*
|
||||
* <h2>AsyncTask's generic types</h2>
|
||||
* <p>The three types used by an asynchronous task are the following:</p>
|
||||
* <ol>
|
||||
* <li><code>Params</code>, the type of the parameters sent to the task upon
|
||||
* execution.</li>
|
||||
* <li><code>Progress</code>, the type of the progress units published during
|
||||
* the background computation.</li>
|
||||
* <li><code>Result</code>, the type of the result of the background
|
||||
* computation.</li>
|
||||
* </ol>
|
||||
* <p>Not all types are always used by an asynchronous task. To mark a type as unused,
|
||||
* simply use the type {@link Void}:</p>
|
||||
* <pre>
|
||||
* private class MyTask extends AsyncTask<Void, Void, Void> { ... }
|
||||
* </pre>
|
||||
*
|
||||
* <h2>The 4 steps</h2>
|
||||
* <p>When an asynchronous task is executed, the task goes through 4 steps:</p>
|
||||
* <ol>
|
||||
* <li>{@link #onPreExecute()}, invoked on the UI thread before the task
|
||||
* is executed. This step is normally used to setup the task, for instance by
|
||||
* showing a progress bar in the user interface.</li>
|
||||
* <li>{@link #doInBackground}, invoked on the background thread
|
||||
* immediately after {@link #onPreExecute()} finishes executing. This step is used
|
||||
* to perform background computation that can take a long time. The parameters
|
||||
* of the asynchronous task are passed to this step. The result of the computation must
|
||||
* be returned by this step and will be passed back to the last step. This step
|
||||
* can also use {@link #publishProgress} to publish one or more units
|
||||
* of progress. These values are published on the UI thread, in the
|
||||
* {@link #onProgressUpdate} step.</li>
|
||||
* <li>{@link #onProgressUpdate}, invoked on the UI thread after a
|
||||
* call to {@link #publishProgress}. The timing of the execution is
|
||||
* undefined. This method is used to display any form of progress in the user
|
||||
* interface while the background computation is still executing. For instance,
|
||||
* it can be used to animate a progress bar or show logs in a text field.</li>
|
||||
* <li>{@link #onPostExecute}, invoked on the UI thread after the background
|
||||
* computation finishes. The result of the background computation is passed to
|
||||
* this step as a parameter.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <h2>Cancelling a task</h2>
|
||||
* <p>A task can be cancelled at any time by invoking {@link #cancel(boolean)}. Invoking
|
||||
* this method will cause subsequent calls to {@link #isCancelled()} to return true.
|
||||
* After invoking this method, {@link #onCancelled(Object)}, instead of
|
||||
* {@link #onPostExecute(Object)} will be invoked after {@link #doInBackground(Object[])}
|
||||
* returns. To ensure that a task is cancelled as quickly as possible, you should always
|
||||
* check the return value of {@link #isCancelled()} periodically from
|
||||
* {@link #doInBackground(Object[])}, if possible (inside a loop for instance.)</p>
|
||||
*
|
||||
* <h2>Threading rules</h2>
|
||||
* <p>There are a few threading rules that must be followed for this class to
|
||||
* work properly:</p>
|
||||
* <ul>
|
||||
* <li>The AsyncTask class must be loaded on the UI thread. This is done
|
||||
* automatically as of {@link android.os.Build.VERSION_CODES#JELLY_BEAN}.</li>
|
||||
* <li>The task instance must be created on the UI thread.</li>
|
||||
* <li>{@link #execute} must be invoked on the UI thread.</li>
|
||||
* <li>Do not call {@link #onPreExecute()}, {@link #onPostExecute},
|
||||
* {@link #doInBackground}, {@link #onProgressUpdate} manually.</li>
|
||||
* <li>The task can be executed only once (an exception will be thrown if
|
||||
* a second execution is attempted.)</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h2>Memory observability</h2>
|
||||
* <p>AsyncTask guarantees that all callback calls are synchronized in such a way that the following
|
||||
* operations are safe without explicit synchronizations.</p>
|
||||
* <ul>
|
||||
* <li>Set member fields in the constructor or {@link #onPreExecute}, and refer to them
|
||||
* in {@link #doInBackground}.
|
||||
* <li>Set member fields in {@link #doInBackground}, and refer to them in
|
||||
* {@link #onProgressUpdate} and {@link #onPostExecute}.
|
||||
* </ul>
|
||||
*
|
||||
* <h2>Order of execution</h2>
|
||||
* <p>When first introduced, AsyncTasks were executed serially on a single background
|
||||
* thread. Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed
|
||||
* to a pool of threads allowing multiple tasks to operate in parallel. Starting with
|
||||
* {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are executed on a single
|
||||
* thread to avoid common application errors caused by parallel execution.</p>
|
||||
* <p>If you truly want parallel execution, you can invoke
|
||||
* {@link #executeOnExecutor(java.util.concurrent.Executor, Object[])} with
|
||||
* {@link #THREAD_POOL_EXECUTOR}.</p>
|
||||
*/
|
||||
public abstract class AsyncTask<Params, Progress, Result> {
|
||||
/**
|
||||
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
|
||||
*/
|
||||
public AsyncTask() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to perform a computation on a background thread. The
|
||||
* specified parameters are the parameters passed to {@link #execute}
|
||||
* by the caller of this task.
|
||||
*
|
||||
* This method can call {@link #publishProgress} to publish updates
|
||||
* on the UI thread.
|
||||
*
|
||||
* @param params The parameters of the task.
|
||||
*
|
||||
* @return A result, defined by the subclass of this task.
|
||||
*
|
||||
* @see #onPreExecute()
|
||||
* @see #onPostExecute
|
||||
* @see #publishProgress
|
||||
*/
|
||||
protected abstract Result doInBackground(Params... params);
|
||||
|
||||
/**
|
||||
* Runs on the UI thread before {@link #doInBackground}.
|
||||
*
|
||||
* @see #onPostExecute
|
||||
* @see #doInBackground
|
||||
*/
|
||||
protected void onPreExecute() {
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Runs on the UI thread after {@link #doInBackground}. The
|
||||
* specified result is the value returned by {@link #doInBackground}.</p>
|
||||
*
|
||||
* <p>This method won't be invoked if the task was cancelled.</p>
|
||||
*
|
||||
* @param result The result of the operation computed by {@link #doInBackground}.
|
||||
*
|
||||
* @see #onPreExecute
|
||||
* @see #doInBackground
|
||||
* @see #onCancelled(Object)
|
||||
*/
|
||||
protected void onPostExecute(Result result) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs on the UI thread after {@link #publishProgress} is invoked.
|
||||
* The specified values are the values passed to {@link #publishProgress}.
|
||||
*
|
||||
* @param values The values indicating progress.
|
||||
*
|
||||
* @see #publishProgress
|
||||
* @see #doInBackground
|
||||
*/
|
||||
protected void onProgressUpdate(Progress... values) {
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and
|
||||
* {@link #doInBackground(Object[])} has finished.</p>
|
||||
*
|
||||
* <p>The default implementation simply invokes {@link #onCancelled()} and
|
||||
* ignores the result. If you write your own implementation, do not call
|
||||
* <code>super.onCancelled(result)</code>.</p>
|
||||
*
|
||||
* @param result The result, if any, computed in
|
||||
* {@link #doInBackground(Object[])}, can be null
|
||||
*
|
||||
* @see #cancel(boolean)
|
||||
* @see #isCancelled()
|
||||
*/
|
||||
protected void onCancelled(Result result) {
|
||||
onCancelled();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Applications should preferably override {@link #onCancelled(Object)}.
|
||||
* This method is invoked by the default implementation of
|
||||
* {@link #onCancelled(Object)}.</p>
|
||||
*
|
||||
* <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and
|
||||
* {@link #doInBackground(Object[])} has finished.</p>
|
||||
*
|
||||
* @see #onCancelled(Object)
|
||||
* @see #cancel(boolean)
|
||||
* @see #isCancelled()
|
||||
*/
|
||||
protected void onCancelled() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this task was cancelled before it completed
|
||||
* normally. If you are calling {@link #cancel(boolean)} on the task,
|
||||
* the value returned by this method should be checked periodically from
|
||||
* {@link #doInBackground(Object[])} to end the task as soon as possible.
|
||||
*
|
||||
* @return <tt>true</tt> if task was cancelled before it completed
|
||||
*
|
||||
* @see #cancel(boolean)
|
||||
*/
|
||||
public final boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Attempts to cancel execution of this task. This attempt will
|
||||
* fail if the task has already completed, already been cancelled,
|
||||
* or could not be cancelled for some other reason. If successful,
|
||||
* and this task has not started when <tt>cancel</tt> is called,
|
||||
* this task should never run. If the task has already started,
|
||||
* then the <tt>mayInterruptIfRunning</tt> parameter determines
|
||||
* whether the thread executing this task should be interrupted in
|
||||
* an attempt to stop the task.</p>
|
||||
*
|
||||
* <p>Calling this method will result in {@link #onCancelled(Object)} being
|
||||
* invoked on the UI thread after {@link #doInBackground(Object[])}
|
||||
* returns. Calling this method guarantees that {@link #onPostExecute(Object)}
|
||||
* is never invoked. After invoking this method, you should check the
|
||||
* value returned by {@link #isCancelled()} periodically from
|
||||
* {@link #doInBackground(Object[])} to finish the task as early as
|
||||
* possible.</p>
|
||||
*
|
||||
* @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
|
||||
* task should be interrupted; otherwise, in-progress tasks are allowed
|
||||
* to complete.
|
||||
*
|
||||
* @return <tt>false</tt> if the task could not be cancelled,
|
||||
* typically because it has already completed normally;
|
||||
* <tt>true</tt> otherwise
|
||||
*
|
||||
* @see #isCancelled()
|
||||
* @see #onCancelled(Object)
|
||||
*/
|
||||
public final boolean cancel(boolean mayInterruptIfRunning) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits if necessary for the computation to complete, and then
|
||||
* retrieves its result.
|
||||
*
|
||||
* @return The computed result.
|
||||
*
|
||||
* @throws CancellationException If the computation was cancelled.
|
||||
* @throws ExecutionException If the computation threw an exception.
|
||||
* @throws InterruptedException If the current thread was interrupted
|
||||
* while waiting.
|
||||
*/
|
||||
public final Result get() throws InterruptedException, ExecutionException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the task with the specified parameters. The task returns
|
||||
* itself (this) so that the caller can keep a reference to it.
|
||||
*
|
||||
* <p>Note: this function schedules the task on a queue for a single background
|
||||
* thread or pool of threads depending on the platform version. When first
|
||||
* introduced, AsyncTasks were executed serially on a single background thread.
|
||||
* Starting with {@link android.os.Build.VERSION_CODES#DONUT}, this was changed
|
||||
* to a pool of threads allowing multiple tasks to operate in parallel. Starting
|
||||
* {@link android.os.Build.VERSION_CODES#HONEYCOMB}, tasks are back to being
|
||||
* executed on a single thread to avoid common application errors caused
|
||||
* by parallel execution. If you truly want parallel execution, you can use
|
||||
* the {@link #executeOnExecutor} version of this method
|
||||
* with {@link #THREAD_POOL_EXECUTOR}; however, see commentary there for warnings
|
||||
* on its use.
|
||||
*
|
||||
* <p>This method must be invoked on the UI thread.
|
||||
*
|
||||
* @param params The parameters of the task.
|
||||
*
|
||||
* @return This instance of AsyncTask.
|
||||
*
|
||||
* @throws IllegalStateException If {@link #getStatus()} returns either
|
||||
* {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
|
||||
*
|
||||
* @see #executeOnExecutor(java.util.concurrent.Executor, Object[])
|
||||
* @see #execute(Runnable)
|
||||
*/
|
||||
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the task with the specified parameters. The task returns
|
||||
* itself (this) so that the caller can keep a reference to it.
|
||||
*
|
||||
* <p>This method is typically used with {@link #THREAD_POOL_EXECUTOR} to
|
||||
* allow multiple tasks to run in parallel on a pool of threads managed by
|
||||
* AsyncTask, however you can also use your own {@link Executor} for custom
|
||||
* behavior.
|
||||
*
|
||||
* <p><em>Warning:</em> Allowing multiple tasks to run in parallel from
|
||||
* a thread pool is generally <em>not</em> what one wants, because the order
|
||||
* of their operation is not defined. For example, if these tasks are used
|
||||
* to modify any state in common (such as writing a file due to a button click),
|
||||
* there are no guarantees on the order of the modifications.
|
||||
* Without careful work it is possible in rare cases for the newer version
|
||||
* of the data to be over-written by an older one, leading to obscure data
|
||||
* loss and stability issues. Such changes are best
|
||||
* executed in serial; to guarantee such work is serialized regardless of
|
||||
* platform version you can use this function with {@link #SERIAL_EXECUTOR}.
|
||||
*
|
||||
* <p>This method must be invoked on the UI thread.
|
||||
*
|
||||
* @param exec The executor to use. {@link #THREAD_POOL_EXECUTOR} is available as a
|
||||
* convenient process-wide thread pool for tasks that are loosely coupled.
|
||||
* @param params The parameters of the task.
|
||||
*
|
||||
* @return This instance of AsyncTask.
|
||||
*
|
||||
* @throws IllegalStateException If {@link #getStatus()} returns either
|
||||
* {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
|
||||
*
|
||||
* @see #execute(Object[])
|
||||
*/
|
||||
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
|
||||
Params... params) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method can be invoked from {@link #doInBackground} to
|
||||
* publish updates on the UI thread while the background computation is
|
||||
* still running. Each call to this method will trigger the execution of
|
||||
* {@link #onProgressUpdate} on the UI thread.
|
||||
*
|
||||
* {@link #onProgressUpdate} will not be called if the task has been
|
||||
* canceled.
|
||||
*
|
||||
* @param values The progress values to update the UI with.
|
||||
*
|
||||
* @see #onProgressUpdate
|
||||
* @see #doInBackground
|
||||
*/
|
||||
protected final void publishProgress(Progress... values) {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user