Merge branch 'main' into atorralba/android-implicit-pending-intents

This commit is contained in:
Tony Torralba
2022-01-18 10:50:49 +01:00
committed by GitHub
160 changed files with 57757 additions and 48141 deletions

View File

@@ -1,3 +1,9 @@
## 0.0.6
### Major Analysis Improvements
* Data flow now propagates taint from remote source `Parameter` types to read steps of their fields (e.g. `tainted.publicField` or `tainted.getField()`). This also applies to their subtypes and the types of their fields, recursively.
## 0.0.5
### Bug Fixes

View File

@@ -1,4 +1,5 @@
---
category: majorAnalysis
---
## 0.0.6
### Major Analysis Improvements
* Data flow now propagates taint from remote source `Parameter` types to read steps of their fields (e.g. `tainted.publicField` or `tainted.getField()`). This also applies to their subtypes and the types of their fields, recursively.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.0.5
lastReleaseVersion: 0.0.6

View File

@@ -1,5 +1,5 @@
name: codeql/java-all
version: 0.0.6-dev
version: 0.0.7-dev
groups: java
dbscheme: config/semmlecode.dbscheme
extractor: java

View File

@@ -115,6 +115,7 @@ private module Frameworks {
private import semmle.code.java.security.AndroidIntentRedirection
private import semmle.code.java.security.ResponseSplitting
private import semmle.code.java.security.InformationLeak
private import semmle.code.java.security.Files
private import semmle.code.java.security.GroovyInjection
private import semmle.code.java.security.ImplicitPendingIntents
private import semmle.code.java.security.JexlInjectionSinkModels
@@ -259,20 +260,6 @@ private predicate sinkModelCsv(string row) {
"java.net;URLClassLoader;false;URLClassLoader;(String,URL[],ClassLoader);;Argument[1];open-url",
"java.net;URLClassLoader;false;URLClassLoader;(String,URL[],ClassLoader,URLStreamHandlerFactory);;Argument[1];open-url",
"java.net;URLClassLoader;false;newInstance;;;Argument[0];open-url",
// Create file
"java.io;FileOutputStream;false;FileOutputStream;;;Argument[0];create-file",
"java.io;RandomAccessFile;false;RandomAccessFile;;;Argument[0];create-file",
"java.io;FileWriter;false;FileWriter;;;Argument[0];create-file",
"java.nio.file;Files;false;move;;;Argument[1];create-file",
"java.nio.file;Files;false;copy;;;Argument[1];create-file",
"java.nio.file;Files;false;newOutputStream;;;Argument[0];create-file",
"java.nio.file;Files;false;newBufferedReader;;;Argument[0];create-file",
"java.nio.file;Files;false;createDirectory;;;Argument[0];create-file",
"java.nio.file;Files;false;createFile;;;Argument[0];create-file",
"java.nio.file;Files;false;createLink;;;Argument[0];create-file",
"java.nio.file;Files;false;createSymbolicLink;;;Argument[0];create-file",
"java.nio.file;Files;false;createTempDirectory;;;Argument[0];create-file",
"java.nio.file;Files;false;createTempFile;;;Argument[0];create-file",
// Bean validation
"javax.validation;ConstraintValidatorContext;true;buildConstraintViolationWithTemplate;;;Argument[0];bean-validation",
// Set hostname

View File

@@ -921,13 +921,15 @@ module Private {
private predicate inputNeedsReference(string c) {
c = "Argument" or
parseArg(c, _)
parseArg(c, _) or
inputNeedsReferenceSpecific(c)
}
private predicate outputNeedsReference(string c) {
c = "Argument" or
parseArg(c, _) or
c = "ReturnValue"
c = "ReturnValue" or
outputNeedsReferenceSpecific(c)
}
private predicate sourceElementRef(InterpretNode ref, string output, string kind) {

View File

@@ -102,6 +102,12 @@ string getParameterPositionCsv(ParameterPosition pos) { result = pos.toString()
/** Gets the textual representation of an argument position in the format used for flow summaries. */
string getArgumentPositionCsv(ArgumentPosition pos) { result = pos.toString() }
/** Holds if input specification component `c` needs a reference. */
predicate inputNeedsReferenceSpecific(string c) { none() }
/** Holds if output specification component `c` needs a reference. */
predicate outputNeedsReferenceSpecific(string c) { none() }
class SourceOrSinkElement = Top;
/**

View File

@@ -0,0 +1,16 @@
/** Provides classes and predicates to track Android fragments. */
import java
/** The class `android.app.Fragment` */
class Fragment extends Class {
Fragment() { this.hasQualifiedName("android.app", "Fragment") }
}
/** The method `instantiate` of the class `android.app.Fragment`. */
class FragmentInstantiateMethod extends Method {
FragmentInstantiateMethod() {
this.getDeclaringType() instanceof Fragment and
this.hasName("instantiate")
}
}

View File

@@ -0,0 +1,101 @@
/**
* Provides classes and predicates to reason about cleartext storage in the Android filesystem
* (external or internal storage).
*/
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.ExternalFlow
import semmle.code.java.security.CleartextStorageQuery
import semmle.code.java.security.Files
import semmle.code.xml.AndroidManifest
private class AndroidFilesystemCleartextStorageSink extends CleartextStorageSink {
AndroidFilesystemCleartextStorageSink() {
filesystemInput(_, this.asExpr()) and
// Make sure we are in an Android application.
exists(AndroidManifestXmlFile manifest)
}
}
/** A call to a method or constructor that may write to files to the local filesystem. */
class LocalFileOpenCall extends Storable {
LocalFileOpenCall() {
this = any(DataFlow::Node sink | sinkNode(sink, "create-file")).asExpr().(Argument).getCall()
}
override Expr getAnInput() {
exists(FilesystemFlowConfig conf, DataFlow::Node n |
filesystemInput(n, result) and
conf.hasFlow(DataFlow::exprNode(this), n)
)
}
override Expr getAStore() {
exists(FilesystemFlowConfig conf, DataFlow::Node n |
closesFile(n, result) and
conf.hasFlow(DataFlow::exprNode(this), n)
)
}
}
/** Holds if `input` is written into `file`. */
private predicate filesystemInput(DataFlow::Node file, Argument input) {
exists(DataFlow::Node write | sinkNode(write, "write-file") |
input = write.asExpr() or
isVarargs(input, write)
) and
if input.getCall().getCallee().isStatic()
then file.asExpr() = input.getCall()
else file.asExpr() = input.getCall().getQualifier()
}
/** Holds if `arg` is part of `varargs`. */
private predicate isVarargs(Argument arg, DataFlow::ImplicitVarargsArray varargs) {
arg.isVararg() and arg.getCall() = varargs.getCall()
}
/** Holds if `store` closes `file`. */
private predicate closesFile(DataFlow::Node file, Call closeCall) {
closeCall.getCallee() instanceof CloseFileMethod and
if closeCall.getCallee().isStatic()
then file.asExpr() = closeCall
else file.asExpr() = closeCall.getQualifier()
or
// try-with-resources automatically closes the file
any(TryStmt try).getAResource() = closeCall.(LocalFileOpenCall).getEnclosingStmt() and
closeCall = file.asExpr()
}
/** A method that closes a file, perhaps after writing some data. */
private class CloseFileMethod extends Method {
CloseFileMethod() {
this.hasQualifiedName("java.io", ["RandomAccessFile", "FileOutputStream", "PrintStream"],
"close")
or
this.getDeclaringType().getASupertype*().hasQualifiedName("java.io", "Writer") and
this.hasName("close")
or
this.hasQualifiedName("java.nio.file", "Files", ["write", "writeString"])
}
}
private class FilesystemFlowConfig extends DataFlow::Configuration {
FilesystemFlowConfig() { this = "FilesystemFlowConfig" }
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof LocalFileOpenCall }
override predicate isSink(DataFlow::Node sink) {
filesystemInput(sink, _) or
closesFile(sink, _)
}
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
// Add nested Writer constructors as extra data flow steps
exists(ClassInstanceExpr cie |
cie.getConstructedType().getASupertype*().hasQualifiedName("java.io", "Writer") and
node1.asExpr() = cie.getArgument(0) and
node2.asExpr() = cie
)
}
}

View File

@@ -0,0 +1,72 @@
/** Provides classes and predicates to work with File objects. */
import java
import semmle.code.java.dataflow.ExternalFlow
private class CreateFileSinkModels extends SinkModelCsv {
override predicate row(string row) {
row =
[
"java.io;FileOutputStream;false;FileOutputStream;;;Argument[0];create-file",
"java.io;RandomAccessFile;false;RandomAccessFile;;;Argument[0];create-file",
"java.io;FileWriter;false;FileWriter;;;Argument[0];create-file",
"java.io;PrintStream;false;PrintStream;(File);;Argument[0];create-file",
"java.io;PrintStream;false;PrintStream;(File,String);;Argument[0];create-file",
"java.io;PrintStream;false;PrintStream;(File,Charset);;Argument[0];create-file",
"java.io;PrintStream;false;PrintStream;(String);;Argument[0];create-file",
"java.io;PrintStream;false;PrintStream;(String,String);;Argument[0];create-file",
"java.io;PrintStream;false;PrintStream;(String,Charset);;Argument[0];create-file",
"java.io;PrintWriter;false;PrintWriter;(File);;Argument[0];create-file",
"java.io;PrintWriter;false;PrintWriter;(File,String);;Argument[0];create-file",
"java.io;PrintWriter;false;PrintWriter;(File,Charset);;Argument[0];create-file",
"java.io;PrintWriter;false;PrintWriter;(String);;Argument[0];create-file",
"java.io;PrintWriter;false;PrintWriter;(String,String);;Argument[0];create-file",
"java.io;PrintWriter;false;PrintWriter;(String,Charset);;Argument[0];create-file",
"java.nio.file;Files;false;copy;;;Argument[1];create-file",
"java.nio.file;Files;false;createDirectories;;;Argument[0];create-file",
"java.nio.file;Files;false;createDirectory;;;Argument[0];create-file",
"java.nio.file;Files;false;createFile;;;Argument[0];create-file",
"java.nio.file;Files;false;createLink;;;Argument[0];create-file",
"java.nio.file;Files;false;createSymbolicLink;;;Argument[0];create-file",
"java.nio.file;Files;false;createTempDirectory;;;Argument[0];create-file",
"java.nio.file;Files;false;createTempFile;(Path,String,String,FileAttribute[]);;Argument[0];create-file",
"java.nio.file;Files;false;move;;;Argument[1];create-file",
"java.nio.file;Files;false;newBufferedWriter;;;Argument[0];create-file",
"java.nio.file;Files;false;newOutputStream;;;Argument[0];create-file",
"java.nio.file;Files;false;write;;;Argument[0];create-file",
"java.nio.file;Files;false;writeString;;;Argument[0];create-file"
]
}
}
private class WriteFileSinkModels extends SinkModelCsv {
override predicate row(string row) {
row =
[
"java.io;FileOutputStream;false;write;;;Argument[0];write-file",
"java.io;RandomAccessFile;false;write;;;Argument[0];write-file",
"java.io;RandomAccessFile;false;writeBytes;;;Argument[0];write-file",
"java.io;RandomAccessFile;false;writeChars;;;Argument[0];write-file",
"java.io;RandomAccessFile;false;writeUTF;;;Argument[0];write-file",
"java.io;Writer;true;append;;;Argument[0];write-file",
"java.io;Writer;true;write;;;Argument[0];write-file",
"java.io;PrintStream;true;append;;;Argument[0];write-file",
"java.io;PrintStream;true;format;(String,Object[]);;Argument[0..1];write-file",
"java.io;PrintStream;true;format;(Locale,String,Object[]);;Argument[1..2];write-file",
"java.io;PrintStream;true;print;;;Argument[0];write-file",
"java.io;PrintStream;true;printf;(String,Object[]);;Argument[0..1];write-file",
"java.io;PrintStream;true;printf;(Locale,String,Object[]);;Argument[1..2];write-file",
"java.io;PrintStream;true;println;;;Argument[0];write-file",
"java.io;PrintStream;true;write;;;Argument[0];write-file",
"java.io;PrintStream;true;writeBytes;;;Argument[0];write-file",
"java.io;PrintWriter;false;format;(String,Object[]);;Argument[0..1];write-file",
"java.io;PrintWriter;false;format;(Locale,String,Object[]);;Argument[1..2];write-file",
"java.io;PrintWriter;false;print;;;Argument[0];write-file",
"java.io;PrintWriter;false;printf;(String,Object[]);;Argument[0..1];write-file",
"java.io;PrintWriter;false;printf;(Locale,String,Object[]);;Argument[1..2];write-file",
"java.io;PrintWriter;false;println;;;Argument[0];write-file",
"java.nio.file;Files;false;write;;;Argument[1];write-file",
"java.nio.file;Files;false;writeString;;;Argument[1];write-file"
]
}
}

View File

@@ -0,0 +1,83 @@
/** Provides classes and predicates to reason about Android Fragment injection vulnerabilities. */
import java
private import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.frameworks.android.Android
private import semmle.code.java.frameworks.android.Fragment
private import semmle.code.java.Reflection
/** The method `isValidFragment` of the class `android.preference.PreferenceActivity`. */
class IsValidFragmentMethod extends Method {
IsValidFragmentMethod() {
this.getDeclaringType()
.getASupertype*()
.hasQualifiedName("android.preference", "PreferenceActivity") and
this.hasName("isValidFragment")
}
/**
* Holds if this method makes the Activity it is declared in vulnerable to Fragment injection,
* that is, all code paths in this method return `true` and the Activity is exported.
*/
predicate isUnsafe() {
this.getDeclaringType().(AndroidActivity).isExported() and
forex(ReturnStmt retStmt | retStmt.getEnclosingCallable() = this |
retStmt.getResult().(BooleanLiteral).getBooleanValue() = true
)
}
}
/**
* A sink for Fragment injection vulnerabilities,
* that is, method calls that dynamically add fragments to activities.
*/
abstract class FragmentInjectionSink extends DataFlow::Node { }
/** An additional taint step for flows related to Fragment injection vulnerabilites. */
class FragmentInjectionAdditionalTaintStep extends Unit {
/**
* Holds if the step from `node1` to `node2` should be considered a taint
* step in flows related to Fragment injection vulnerabilites.
*/
abstract predicate step(DataFlow::Node n1, DataFlow::Node n2);
}
private class FragmentInjectionSinkModels extends SinkModelCsv {
override predicate row(string row) {
row =
["android.app", "android.support.v4.app", "androidx.fragment.app"] +
";FragmentTransaction;true;" +
[
"add;(Class,Bundle,String);;Argument[0]", "add;(Fragment,String);;Argument[0]",
"add;(int,Class,Bundle);;Argument[1]", "add;(int,Fragment);;Argument[1]",
"add;(int,Class,Bundle,String);;Argument[1]", "add;(int,Fragment,String);;Argument[1]",
"attach;(Fragment);;Argument[0]", "replace;(int,Class,Bundle);;Argument[1]",
"replace;(int,Fragment);;Argument[1]", "replace;(int,Class,Bundle,String);;Argument[1]",
"replace;(int,Fragment,String);;Argument[1]",
] + ";fragment-injection"
}
}
private class DefaultFragmentInjectionSink extends FragmentInjectionSink {
DefaultFragmentInjectionSink() { sinkNode(this, "fragment-injection") }
}
private class DefaultFragmentInjectionAdditionalTaintStep extends FragmentInjectionAdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(ReflectiveClassIdentifierMethodAccess ma |
ma.getArgument(0) = n1.asExpr() and ma = n2.asExpr()
)
or
exists(NewInstance ni |
ni.getQualifier() = n1.asExpr() and
ni = n2.asExpr()
)
or
exists(MethodAccess ma |
ma.getMethod() instanceof FragmentInstantiateMethod and
ma.getArgument(1) = n1.asExpr() and
ma = n2.asExpr()
)
}
}

View File

@@ -0,0 +1,22 @@
/** Provides classes and predicates to be used in queries related to Android Fragment injection. */
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.security.FragmentInjection
/**
* A taint-tracking configuration for unsafe user input
* that is used to create Android fragments dynamically.
*/
class FragmentInjectionTaintConf extends TaintTracking::Configuration {
FragmentInjectionTaintConf() { this = "FragmentInjectionTaintConf" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof FragmentInjectionSink }
override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) {
any(FragmentInjectionAdditionalTaintStep c).step(n1, n2)
}
}

View File

@@ -1,4 +1,4 @@
/** Provides clases and methods shared by randomness-related queries. */
/** Provides classes and methods shared by randomness-related queries. */
import java
import semmle.code.java.dataflow.DefUse

View File

@@ -1,3 +1,5 @@
## 0.0.6
## 0.0.5
### Minor Analysis Improvements

View File

@@ -0,0 +1,36 @@
public void fileSystemStorageUnsafe(String name, String password) {
// BAD - sensitive data stored in cleartext
FileWriter fw = new FileWriter("some_file.txt");
fw.write(name + ":" + password);
fw.close();
}
public void filesystemStorageEncryptedFileSafe(Context context, String name, String password) {
// GOOD - the whole file is encrypted with androidx.security.crypto.EncryptedFile
File file = new File("some_file.txt");
String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);
EncryptedFile encryptedFile = new EncryptedFile.Builder(
file,
context,
masterKeyAlias,
EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build();
FileOutputStream encryptedOutputStream = encryptedFile.openFileOutput();
encryptedOutputStream.write(name + ":" + password);
}
public void fileSystemStorageSafe(String name, String password) {
// GOOD - sensitive data is encrypted using a custom method
FileWriter fw = new FileWriter("some_file.txt");
fw.write(name + ":" + encrypt(password));
fw.close();
}
private static String encrypt(String cleartext) {
// Use an encryption or strong hashing algorithm in the real world.
// The example below just returns a SHA-256 hash.
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(cleartext.getBytes(StandardCharsets.UTF_8));
String encoded = Base64.getEncoder().encodeToString(hash);
return encoded;
}

View File

@@ -0,0 +1,35 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>
Android applications with the appropriate permissions can write files either to the device external storage or the application internal storage, depending on the application's needs. However, sensitive information should not be saved in cleartext. Otherwise it can be accessed by any process or user in rooted devices, or can be disclosed through chained vulnerabilities, like unexpected access to the private storage through exposed components.
</p>
</overview>
<recommendation>
<p>
Consider using the <code>EncryptedFile</code> class to work with files containing sensitive data. Alternatively, use encryption algorithms to encrypt the sensitive data being stored.
</p>
</recommendation>
<example>
<p>
In the first example, sensitive user information is stored in cleartext using a local file.
</p>
<p>
In the second and third examples, the code encrypts sensitive information before saving it to the filesystem.
</p>
<sample src="CleartextStorageAndroidFilesystem.java" />
</example>
<references>
<li>
Android Developers:
<a href="https://developer.android.com/topic/security/data">Work with data more securely</a>
</li>
<li>
Android Developers:
<a href="https://developer.android.com/reference/androidx/security/crypto/EncryptedFile">EncryptedFile</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,23 @@
/**
* @name Cleartext storage of sensitive information in the Android filesystem
* @description Cleartext storage of sensitive information in the Android filesystem
* allows access for users with root privileges or unexpected exposure
* from chained vulnerabilities.
* @kind problem
* @problem.severity warning
* @precision medium
* @id java/android/cleartext-storage-filesystem
* @tags security
* external/cwe/cwe-312
*/
import java
import semmle.code.java.security.CleartextStorageAndroidFilesystemQuery
from SensitiveSource data, LocalFileOpenCall s, Expr input, Expr store
where
input = s.getAnInput() and
store = s.getAStore() and
data.flowsTo(input)
select store, "Local file $@ containing $@ is stored $@. Data was added $@.", s, s.toString(), data,
"sensitive data", store, "here", input, "here"

View File

@@ -0,0 +1,60 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>
When fragments are instantiated with externally provided names, this exposes any exported activity that dynamically
creates and hosts the fragment to fragment injection. A malicious application could provide the
name of an arbitrary fragment, even one not designed to be externally accessible, and inject it into the activity.
This can bypass access controls and expose the application to unintended effects.
</p>
<p>
Fragments are reusable parts of an Android application's user interface.
Even though a fragment controls its own lifecycle and layout, and handles its input events,
it cannot exist on its own: it must be hosted either by an activity or another fragment.
This means that, normally, a fragment will be accessible by third-party applications (that is, exported)
only if its hosting activity is itself exported.
</p>
</overview>
<recommendation>
<p>
In general, do not instantiate classes (including fragments) with user-provided names
unless the name has been properly validated.
Also, if an exported activity is extending the <code>PreferenceActivity</code> class, make sure that
the <code>isValidFragment</code> method is overriden and only returns <code>true</code> when the provided
<code>fragmentName</code> points to an intended fragment.
</p>
</recommendation>
<example>
<p>
The following example shows two cases: in the first one, untrusted data is used to instantiate and
add a fragment to an activity, while in the second one, a fragment is safely added with a static name.
</p>
<sample src="FragmentInjection.java" />
<p>
The next example shows two activities that extend <code>PreferenceActivity</code>. The first activity overrides
<code>isValidFragment</code>, but it wrongly returns <code>true</code> unconditionally. The second activity
correctly overrides <code>isValidFragment</code> so that it only returns <code>true</code> when <code>fragmentName</code>
is a trusted fragment name.
</p>
<sample src="FragmentInjectionInPreferenceActivity.java" />
</example>
<references>
<li> Google Help:
<a href="https://support.google.com/faqs/answer/7188427?hl=en">How to fix Fragment Injection vulnerability</a>.
</li>
<li>
IBM Security Systems:
<a href="https://securityintelligence.com/wp-content/uploads/2013/12/android-collapses-into-fragments.pdf">Android collapses into Fragments</a>.
</li>
<li>
Android Developers:
<a href="https://developer.android.com/guide/fragments">Fragments</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,22 @@
public class MyActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstance) {
try {
super.onCreate(savedInstance);
// BAD: Fragment instantiated from user input without validation
{
String fName = getIntent().getStringExtra("fragmentName");
getFragmentManager().beginTransaction().replace(com.android.internal.R.id.prefs,
Fragment.instantiate(this, fName, null)).commit();
}
// GOOD: Fragment instantiated statically
{
getFragmentManager().beginTransaction()
.replace(com.android.internal.R.id.prefs, new MyFragment()).commit();
}
} catch (Exception e) {
}
}
}

View File

@@ -0,0 +1,4 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<include src="FragmentInjection.inc.qhelp"></include>
</qhelp>

View File

@@ -0,0 +1,21 @@
/**
* @name Android fragment injection
* @description Instantiating an Android fragment from a user-provided value
* may allow a malicious application to bypass access controls, exposing the application to unintended effects.
* @kind path-problem
* @problem.severity error
* @security-severity 9.8
* @precision high
* @id java/android/fragment-injection
* @tags security
* external/cwe/cwe-470
*/
import java
import semmle.code.java.security.FragmentInjectionQuery
import DataFlow::PathGraph
from DataFlow::PathNode source, DataFlow::PathNode sink
where any(FragmentInjectionTaintConf conf).hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Fragment injection from $@.", source.getNode(),
"this user input"

View File

@@ -0,0 +1,21 @@
class UnsafeActivity extends PreferenceActivity {
@Override
protected boolean isValidFragment(String fragmentName) {
// BAD: any Fragment name can be provided.
return true;
}
}
class SafeActivity extends PreferenceActivity {
@Override
protected boolean isValidFragment(String fragmentName) {
// Good: only trusted Fragment names are allowed.
return SafeFragment1.class.getName().equals(fragmentName)
|| SafeFragment2.class.getName().equals(fragmentName)
|| SafeFragment3.class.getName().equals(fragmentName);
}
}

View File

@@ -0,0 +1,4 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<include src="FragmentInjection.inc.qhelp"></include>
</qhelp>

View File

@@ -0,0 +1,22 @@
/**
* @name Android fragment injection in PreferenceActivity
* @description An insecure implementation of the 'isValidFragment' method
* of the 'PreferenceActivity' class may allow a malicious application to bypass access controls,
* exposing the application to unintended effects.
* @kind problem
* @problem.severity error
* @security-severity 9.8
* @precision high
* @id java/android/fragment-injection-preference-activity
* @tags security
* external/cwe/cwe-470
*/
import java
import semmle.code.java.security.FragmentInjection
from IsValidFragmentMethod m
where m.isUnsafe()
select m,
"The 'isValidFragment' method always returns true. This makes the exported Activity $@ vulnerable to Fragment Injection.",
m.getDeclaringType(), m.getDeclaringType().getName()

View File

@@ -0,0 +1,4 @@
---
category: newQuery
---
* A new query "Cleartext storage of sensitive information in the Android filesystem" (`java/android/cleartext-storage-filesystem`) has been added. This query finds instances of sensitive data being stored in local files without encryption, which may expose it to attackers or malicious applications.

View File

@@ -0,0 +1,5 @@
---
category: newQuery
---
* Two new queries, "Android fragment injection" (`java/android/fragment-injection`) and "Android fragment injection in PreferenceActivity" (`java/android/fragment-injection-preference-activity`) have been added.
These queries find exported Android activities that instantiate and host fragments created from user-provided data. Such activities are vulnerable to access control bypass and expose the Android application to unintended effects.

View File

@@ -0,0 +1 @@
## 0.0.6

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.0.5
lastReleaseVersion: 0.0.6

View File

@@ -1,5 +1,5 @@
name: codeql/java-queries
version: 0.0.6-dev
version: 0.0.7-dev
groups: java
suites: codeql-suites
extractor: java

View File

@@ -1,4 +1,3 @@
| java.io.PrintStream#println(Object) | 3 |
| java.lang.Class#isAssignableFrom(Class) | 1 |
| java.lang.String#length() | 1 |
| java.time.Duration#ofMillis(long) | 1 |

View File

@@ -0,0 +1,13 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app"
android:installLocation="auto"
android:versionCode="1"
android:versionName="0.1" >
<application>
<activity android:name=".CleartextStorageAndroidDatabaseTest"></activity>
<activity android:name=".CleartextStorageAndroidFileSystemTest"></activity>
<activity android:name=".CleartextStorageSharedPrefsTest"></activity>
</application>
</manifest>

View File

@@ -0,0 +1,277 @@
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.MessageDigest;
import java.util.Base64;
import java.util.List;
import java.util.Locale;
import android.app.Activity;
import android.content.Context;
import androidx.security.crypto.EncryptedFile;
import androidx.security.crypto.EncryptedFile.FileEncryptionScheme;
public class CleartextStorageAndroidFilesystemTest extends Activity {
public void testWriteLocalFile(Context context, String name, String password) throws Exception {
// FileOutputStream
{
// java.io;FileOutputStream;false;FileOutputStream;;;Argument[0];create-file
FileOutputStream os = new FileOutputStream("some_file.txt");
// Nested writers
Writer writer = new BufferedWriter(new OutputStreamWriter(os, "utf-8"));
// java.io;FileOutputStream;false;write;;;Argument[0];write-file
writer.write(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
writer.close();
}
// RandomAccessFile
{
// java.io;RandomAccessFile;false;RandomAccessFile;;;Argument[0];create-file
RandomAccessFile f = new RandomAccessFile("some_file.txt", "r");
String contents = name + ":" + password;
// java.io;RandomAccessFile;false;write;;;Argument[0];write-file
f.write(contents.getBytes()); // $ hasCleartextStorageAndroidFilesystem
f.close();
}
{
// try-with-resources
try (RandomAccessFile f = new RandomAccessFile(new File("some_file.txt"), "r")) {
// java.io;RandomAccessFile;false;writeBytes;;;Argument[0];write-file
f.writeBytes(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
}
}
{
RandomAccessFile f = new RandomAccessFile("some_file.txt", "r");
// java.io;RandomAccessFile;false;writeChars;;;Argument[0];write-file
f.writeChars(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
f.close();
}
{
RandomAccessFile f = new RandomAccessFile("some_file.txt", "r");
// java.io;RandomAccessFile;false;writeUTF;;;Argument[0];write-file
f.writeUTF(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
f.close();
}
// FileWriter
{
// java.io;FileWriter;false;FileWriter;;;Argument[0];create-file
FileWriter fw = new FileWriter("some_file.txt");
// java.io;Writer;true;append;;;Argument[0];write-file
fw.append(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
fw.close();
}
{
// try-with-resources
try (FileWriter fw = new FileWriter("some_file.txt")) {
// java.io;Writer;true;write;;;Argument[0];write-file
fw.write(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
}
}
// PrintStream
{
// java.io;PrintStream;false;PrintStream;(File);;Argument[0];create-file"
PrintStream ps = new PrintStream(new File("some_file.txt"));
// java.io;PrintStream;true;append;;;Argument[0];write-file
ps.append(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
ps.close();
}
{
// java.io;PrintStream;false;PrintStream;(File,String);;Argument[0];create-file
PrintStream ps = new PrintStream(new File("some_file.txt"), "utf-8");
// java.io;PrintStream;true;format;(String,Object[]);;Argument[0..1];write-file
ps.format("%s:" + password, name); // $ hasCleartextStorageAndroidFilesystem
ps.format("%s:%s", name, password); // $ hasCleartextStorageAndroidFilesystem
ps.close();
}
{
// java.io;PrintStream;false;PrintStream;(File,Charset);;Argument[0];create-file
PrintStream ps = new PrintStream(new File("some_file.txt"), Charset.defaultCharset());
// java.io;PrintStream;true;format;(Locale,String,Object[]);;Argument[1..2];write-file
ps.format(Locale.US, "%s:" + password, name); // $ hasCleartextStorageAndroidFilesystem
ps.format(Locale.US, "%s:%s", name, password); // $ hasCleartextStorageAndroidFilesystem
ps.close();
}
{
// java.io;PrintStream;false;PrintStream;(String);;Argument[0];create-file
PrintStream ps = new PrintStream("some_file.txt");
// java.io;PrintStream;true;print;;;Argument[0];write-file
ps.print(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
ps.close();
}
{
// java.io;PrintStream;false;PrintStream;(String,String);;Argument[0];create-file
PrintStream ps = new PrintStream("some_file.txt", "utf-8");
// java.io;PrintStream;true;printf;(String,Object[]);;Argument[0..1];write-file
ps.printf("%s:" + password, name); // $ hasCleartextStorageAndroidFilesystem
ps.printf("%s:%s", name, password); // $ hasCleartextStorageAndroidFilesystem
ps.close();
}
{
// java.io;PrintStream;false;PrintStream;(String,Charset);;Argument[0];create-file
PrintStream ps = new PrintStream("some_file.txt", Charset.defaultCharset());
// java.io;PrintStream;true;printf;(Locale,String,Object[]);;Argument[1..2];write-file
ps.printf(Locale.US, "%s:" + password, name); // $ hasCleartextStorageAndroidFilesystem
ps.printf(Locale.US, "%s:%s", name, password); // $ hasCleartextStorageAndroidFilesystem
ps.close();
}
{
PrintStream ps = new PrintStream("some_file.txt");
// java.io;PrintStream;true;println;;;Argument[0];write-file
ps.println(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
ps.close();
}
{
PrintStream ps = new PrintStream("some_file.txt");
String contents = name + ":" + password;
// java.io;PrintStream;true;write;;;Argument[0];write-file
ps.write(contents.getBytes()); // $ hasCleartextStorageAndroidFilesystem
ps.close();
}
{
PrintStream ps = new PrintStream("some_file.txt");
String contents = name + ":" + password;
// java.io;PrintStream;true;writeBytes;;;Argument[0];write-file
ps.writeBytes(contents.getBytes()); // $ hasCleartextStorageAndroidFilesystem
ps.close();
}
// PrintWriter
{
// java.io;PrintWriter;false;PrintWriter;(File);;Argument[0];create-file
PrintWriter pw = new PrintWriter(new File("some_file.txt"));
// java.io;Writer;true;append;;;Argument[0];write-file
pw.append(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
pw.close();
}
{
// try-with-resources
try (PrintWriter pw = new PrintWriter(new File("some_file.txt"))) {
// java.io;PrintWriter;false;format;(String,Object[]);;Argument[0..1];write-file
pw.format("%s:" + password, name); // $ hasCleartextStorageAndroidFilesystem
pw.format("%s:%s", name, password); // $ hasCleartextStorageAndroidFilesystem
}
}
{
// java.io;PrintWriter;false;PrintWriter;(File,String);;Argument[0];create-file
PrintWriter pw = new PrintWriter(new File("some_file.txt"), "utf-8");
// java.io;PrintWriter;false;format;(Locale,String,Object[]);;Argument[1..2];write-file
pw.format(Locale.US, "%s:" + password, name); // $ hasCleartextStorageAndroidFilesystem
pw.format(Locale.US, "%s:%s", name, password); // $ hasCleartextStorageAndroidFilesystem
pw.close();
}
{
// java.io;PrintWriter;false;PrintWriter;(File,Charset);;Argument[0];create-file
PrintWriter pw = new PrintWriter(new File("some_file.txt"), Charset.defaultCharset());
// java.io;PrintWriter;false;print;;;Argument[0];write-file
pw.print(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
pw.close();
}
{
// java.io;PrintWriter;false;PrintWriter;(String);;Argument[0];create-file
PrintWriter pw = new PrintWriter("some_file.txt");
// java.io;PrintWriter;false;printf;(String,Object[]);;Argument[0..1];write-file
pw.printf("%s:" + password, name); // $ hasCleartextStorageAndroidFilesystem
pw.printf("%s:%s", name, password); // $ hasCleartextStorageAndroidFilesystem
pw.close();
}
{
// java.io;PrintWriter;false;PrintWriter;(String,String);;Argument[0];create-file
PrintWriter pw = new PrintWriter("some_file.txt", "utf-8");
// java.io;PrintWriter;false;printf;(Locale,String,Object[]);;Argument[1..2];write-file
pw.printf(Locale.US, "%s:" + password, name); // $ hasCleartextStorageAndroidFilesystem
pw.printf(Locale.US, "%s:%s", name, password); // $ hasCleartextStorageAndroidFilesystem
pw.close();
}
{
// java.io;PrintWriter;false;PrintWriter;(String,Charset);;Argument[0];create-file
PrintWriter pw = new PrintWriter("some_file.txt", Charset.defaultCharset());
// java.io;PrintWriter;false;println;;;Argument[0];write-file
pw.println(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
pw.close();
}
{
PrintWriter pw = new PrintWriter("some_file.txt");
// java.io;Writer;true;write;;;Argument[0];write-file
pw.write(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
pw.close();
}
// java.nio.files.Files
{
// java.nio.file;Files;false;newBufferedWriter;;;Argument[0];create-file
BufferedWriter bw = Files.newBufferedWriter(Path.of("some_file.txt"));
bw.write(name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
bw.close();
}
{
// java.nio.file;Files;false;newOutputStream;;;Argument[0];create-file
// try-with-resources
try (OutputStream os = Files.newOutputStream(Path.of("some_file.txt"))) {
String contents = name + ":" + password;
os.write(contents.getBytes());
}
}
{
Path path = Path.of("some_file.txt");
String contents = name + ":" + password;
// java.nio.file;Files;false;write;;;Argument[0];create-file
// java.nio.file;Files;false;write;;;Argument[1];write-file",
Files.write(path, contents.getBytes()); // $ hasCleartextStorageAndroidFilesystem
}
{
Path path = Path.of("some_file.txt");
String contents = name + ":" + password;
Files.write(path, List.of(contents)); // $ hasCleartextStorageAndroidFilesystem
}
{
Path path = Path.of("some_file.txt");
// java.nio.file;Files;false;writeString;;;Argument[0];create-file
// java.nio.file;Files;false;writeString;;;Argument[1];write-file"
Files.writeString(path, name + ":" + password); // $ hasCleartextStorageAndroidFilesystem
}
// Safe writes
{
FileWriter fw = new FileWriter("some_file.txt");
fw.write(name + ":" + hash(password)); // Safe - using a hash
fw.close();
}
{
Writer writer = new OutputStreamWriter(new ByteArrayOutputStream(), "utf-8");
writer.write(name + ":" + password); // Safe - not writing to a file
writer.close();
}
{
File file = new File("some_file.txt");
String contents = name + ":" + password;
EncryptedFile encryptedFile = new EncryptedFile.Builder(file, context, "some_key",
FileEncryptionScheme.AES256_GCM_HKDF_4KB).build();
FileOutputStream encryptedOutputStream = encryptedFile.openFileOutput();
encryptedOutputStream.write(contents.getBytes()); // Safe - using EncryptedFile
}
}
private static String hash(String cleartext) throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(cleartext.getBytes(StandardCharsets.UTF_8));
String encoded = Base64.getEncoder().encodeToString(hash);
return encoded;
}
}

View File

@@ -0,0 +1,22 @@
import java
import semmle.code.java.security.CleartextStorageAndroidFilesystemQuery
import TestUtilities.InlineExpectationsTest
class CleartextStorageAndroidFilesystemTest extends InlineExpectationsTest {
CleartextStorageAndroidFilesystemTest() { this = "CleartextStorageAndroidFilesystemTest" }
override string getARelevantTag() { result = "hasCleartextStorageAndroidFilesystem" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasCleartextStorageAndroidFilesystem" and
exists(SensitiveSource data, LocalFileOpenCall s, Expr input, Expr store |
input = s.getAnInput() and
store = s.getAStore() and
data.flowsTo(input)
|
input.getLocation() = location and
element = input.toString() and
value = ""
)
}
}

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
package="com.example.myapp">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SafePreferenceActivity" android:exported="true" />
<activity android:name=".UnsafePreferenceActivity" android:exported="true" />
<activity android:name=".UnexportedPreferenceActivity" android:exported="false" />
</application>
</manifest>

View File

@@ -0,0 +1,18 @@
import java
import semmle.code.java.security.FragmentInjection
import TestUtilities.InlineExpectationsTest
class FragmentInjectionInPreferenceActivityTest extends InlineExpectationsTest {
FragmentInjectionInPreferenceActivityTest() { this = "FragmentInjectionInPreferenceActivityTest" }
override string getARelevantTag() { result = "hasPreferenceFragmentInjection" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasPreferenceFragmentInjection" and
exists(IsValidFragmentMethod isValidFragment | isValidFragment.isUnsafe() |
isValidFragment.getLocation() = location and
element = isValidFragment.toString() and
value = ""
)
}
}

View File

@@ -0,0 +1,11 @@
import java
import semmle.code.java.security.FragmentInjectionQuery
import TestUtilities.InlineFlowTest
class Test extends InlineFlowTest {
override DataFlow::Configuration getValueFlowConfig() { none() }
override TaintTracking::Configuration getTaintFlowConfig() {
result instanceof FragmentInjectionTaintConf
}
}

View File

@@ -0,0 +1,39 @@
package com.example.myapp;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentTransaction;
public class MainActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstance) {
try {
super.onCreate(savedInstance);
final String fname = getIntent().getStringExtra("fname");
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Class<Fragment> fClass = (Class<Fragment>) Class.forName(fname);
ft.add(fClass.newInstance(), ""); // $ hasTaintFlow
ft.add(0, Fragment.instantiate(this, fname), null); // $ hasTaintFlow
ft.add(0, Fragment.instantiate(this, fname, null)); // $ hasTaintFlow
ft.add(0, fClass, null, ""); // $ hasTaintFlow
ft.add(0, fClass.newInstance(), ""); // $ hasTaintFlow
ft.attach(fClass.newInstance()); // $ hasTaintFlow
ft.replace(0, fClass, null); // $ hasTaintFlow
ft.replace(0, fClass.newInstance()); // $ hasTaintFlow
ft.replace(0, fClass, null, ""); // $ hasTaintFlow
ft.replace(0, fClass.newInstance(), ""); // $ hasTaintFlow
ft.add(Fragment.class.newInstance(), ""); // Safe
ft.attach(Fragment.class.newInstance()); // Safe
ft.replace(0, Fragment.class.newInstance(), ""); // Safe
} catch (Exception e) {
}
}
}

View File

@@ -0,0 +1,11 @@
package com.example.myapp;
import android.preference.PreferenceActivity;
public class SafePreferenceActivity extends PreferenceActivity {
@Override
protected boolean isValidFragment(String fragmentName) { // Safe: not all paths return true
return fragmentName.equals("MySafeFragment") || fragmentName.equals("MySafeFragment2");
}
}

View File

@@ -0,0 +1,11 @@
package com.example.myapp;
import android.preference.PreferenceActivity;
public class UnexportedPreferenceActivity extends PreferenceActivity {
@Override
protected boolean isValidFragment(String fragmentName) { // Safe: not exported
return true;
}
}

View File

@@ -0,0 +1,11 @@
package com.example.myapp;
import android.preference.PreferenceActivity;
public class UnsafePreferenceActivity extends PreferenceActivity {
@Override
protected boolean isValidFragment(String fragmentName) { // $ hasPreferenceFragmentInjection
return true;
}
}

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/google-android-9.0.0

View File

@@ -16,6 +16,7 @@ package android.app;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;

View File

@@ -0,0 +1,30 @@
/*
* 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;
public class ListActivity extends Activity {
public void onContentChanged() {}
public void setSelection(int position) {}
public int getSelectedItemPosition() {
return 0;
}
public long getSelectedItemId() {
return 0;
}
}

View File

@@ -2,10 +2,7 @@
package android.content;
import android.content.ComponentCallbacks;
public interface ComponentCallbacks2 extends ComponentCallbacks
{
public interface ComponentCallbacks2 extends ComponentCallbacks {
static int TRIM_MEMORY_BACKGROUND = 0;
static int TRIM_MEMORY_COMPLETE = 0;
static int TRIM_MEMORY_MODERATE = 0;
@@ -13,5 +10,6 @@ public interface ComponentCallbacks2 extends ComponentCallbacks
static int TRIM_MEMORY_RUNNING_LOW = 0;
static int TRIM_MEMORY_RUNNING_MODERATE = 0;
static int TRIM_MEMORY_UI_HIDDEN = 0;
void onTrimMemory(int p0);
}

View File

@@ -0,0 +1,139 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package android.preference;
import java.util.List;
import android.app.Fragment;
import android.app.ListActivity;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.view.View;
import android.view.View.OnClickListener;
public abstract class PreferenceActivity extends ListActivity {
public static final class Header implements Parcelable {
public Header() {}
public CharSequence getTitle(Resources res) {
return null;
}
public CharSequence getSummary(Resources res) {
return null;
}
public CharSequence getBreadCrumbTitle(Resources res) {
return null;
}
public CharSequence getBreadCrumbShortTitle(Resources res) {
return null;
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {}
public void readFromParcel(Parcel in) {}
public static final Creator<Header> CREATOR = null;
}
public void onBackPressed() {}
public boolean hasHeaders() {
return false;
}
public List<Header> getHeaders() {
return null;
}
public boolean isMultiPane() {
return false;
}
public boolean onIsMultiPane() {
return false;
}
public boolean onIsHidingHeaders() {
return false;
}
public Header onGetInitialHeader() {
return null;
}
public Header onGetNewHeader() {
return null;
}
public void onBuildHeaders(List<Header> target) {}
public void invalidateHeaders() {}
public void loadHeadersFromResource(int resid, List<Header> target) {}
public void setListFooter(View view) {}
public void onContentChanged() {}
public void onHeaderClick(Header header, int position) {}
public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args, int titleRes,
int shortTitleRes) {
return null;
}
public void startWithFragment(String fragmentName, Bundle args, Fragment resultTo,
int resultRequestCode) {}
public void startWithFragment(String fragmentName, Bundle args, Fragment resultTo,
int resultRequestCode, int titleRes, int shortTitleRes) {}
public void showBreadCrumbs(CharSequence title, CharSequence shortTitle) {}
public void setParentTitle(CharSequence title, CharSequence shortTitle,
OnClickListener listener) {}
public void switchToHeader(String fragmentName, Bundle args) {}
public void switchToHeader(Header header) {}
public void startPreferenceFragment(Fragment fragment, boolean push) {}
public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes,
CharSequence titleText, Fragment resultTo, int resultRequestCode) {}
public void finishPreferencePanel(Fragment caller, int resultCode, Intent resultData) {}
public void addPreferencesFromIntent(Intent intent) {}
public void addPreferencesFromResource(int preferencesResId) {}
protected boolean isValidFragment(String fragmentName) {
return false;
}
}

View File

@@ -0,0 +1,42 @@
/*
* 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.widget;
import android.content.Context;
import android.util.AttributeSet;
public class Button extends TextView {
public Button(Context context) {
super(null);
}
public Button(Context context, AttributeSet attrs) {
super(null);
}
public Button(Context context, AttributeSet attrs, int defStyleAttr) {
super(null);
}
public Button(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(null);
}
@Override
public CharSequence getAccessibilityClassName() {
return null;
}
}

View File

@@ -0,0 +1,816 @@
/*
* 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.widget;
import java.util.ArrayList;
import java.util.Locale;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.BlendMode;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.LocaleList;
import android.os.UserHandle;
import android.util.AttributeSet;
import android.view.View;
public class TextView extends View {
public @interface XMLTypefaceAttr {
}
public @interface AutoSizeTextType {
}
public static void preloadFontCache() {}
public TextView(Context context) {
super(null);
}
public TextView(Context context, AttributeSet attrs) {
super(null);
}
public TextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(null);
}
public TextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(null);
}
public void setAutoSizeTextTypeWithDefaults(int autoSizeTextType) {}
public void setAutoSizeTextTypeUniformWithConfiguration(int autoSizeMinTextSize,
int autoSizeMaxTextSize, int autoSizeStepGranularity, int unit) {}
public void setAutoSizeTextTypeUniformWithPresetSizes(int[] presetSizes, int unit) {}
public int getAutoSizeTextType() {
return 0;
}
public int getAutoSizeStepGranularity() {
return 0;
}
public int getAutoSizeMinTextSize() {
return 0;
}
public int getAutoSizeMaxTextSize() {
return 0;
}
public int[] getAutoSizeTextAvailableSizes() {
return null;
}
public void setTypeface(Typeface tf, int style) {}
public CharSequence getText() {
return null;
}
public int length() {
return 0;
}
public CharSequence getTransformed() {
return null;
}
public int getLineHeight() {
return 0;
}
public int getCompoundPaddingTop() {
return 0;
}
public int getCompoundPaddingBottom() {
return 0;
}
public int getCompoundPaddingLeft() {
return 0;
}
public int getCompoundPaddingRight() {
return 0;
}
public int getCompoundPaddingStart() {
return 0;
}
public int getCompoundPaddingEnd() {
return 0;
}
public int getExtendedPaddingTop() {
return 0;
}
public int getExtendedPaddingBottom() {
return 0;
}
public int getTotalPaddingLeft() {
return 0;
}
public int getTotalPaddingRight() {
return 0;
}
public int getTotalPaddingStart() {
return 0;
}
public int getTotalPaddingEnd() {
return 0;
}
public int getTotalPaddingTop() {
return 0;
}
public int getTotalPaddingBottom() {
return 0;
}
public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom) {}
public void setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom) {}
public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top, Drawable right,
Drawable bottom) {}
public void setCompoundDrawablesRelative(Drawable start, Drawable top, Drawable end,
Drawable bottom) {}
public void setCompoundDrawablesRelativeWithIntrinsicBounds(int start, int top, int end,
int bottom) {}
public void setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top,
Drawable end, Drawable bottom) {}
public Drawable[] getCompoundDrawables() {
return null;
}
public Drawable[] getCompoundDrawablesRelative() {
return null;
}
public void setCompoundDrawablePadding(int pad) {}
public int getCompoundDrawablePadding() {
return 0;
}
public void setCompoundDrawableTintList(ColorStateList tint) {}
public ColorStateList getCompoundDrawableTintList() {
return null;
}
public void setCompoundDrawableTintMode(PorterDuff.Mode tintMode) {}
public void setCompoundDrawableTintBlendMode(BlendMode blendMode) {}
public PorterDuff.Mode getCompoundDrawableTintMode() {
return null;
}
public BlendMode getCompoundDrawableTintBlendMode() {
return null;
}
public void setFirstBaselineToTopHeight(int firstBaselineToTopHeight) {}
public void setLastBaselineToBottomHeight(int lastBaselineToBottomHeight) {}
public int getFirstBaselineToTopHeight() {
return 0;
}
public int getLastBaselineToBottomHeight() {
return 0;
}
public final int getAutoLinkMask() {
return 0;
}
public void setTextSelectHandle(Drawable textSelectHandle) {}
public void setTextSelectHandle(int textSelectHandle) {}
@Nullable
public Drawable getTextSelectHandle() {
return null;
}
public void setTextSelectHandleLeft(Drawable textSelectHandleLeft) {}
public void setTextSelectHandleLeft(int textSelectHandleLeft) {}
@Nullable
public Drawable getTextSelectHandleLeft() {
return null;
}
public void setTextSelectHandleRight(Drawable textSelectHandleRight) {}
public void setTextSelectHandleRight(int textSelectHandleRight) {}
@Nullable
public Drawable getTextSelectHandleRight() {
return null;
}
public void setTextCursorDrawable(Drawable textCursorDrawable) {}
public void setTextCursorDrawable(int textCursorDrawable) {}
@Nullable
public Drawable getTextCursorDrawable() {
return null;
}
public void setTextAppearance(int resId) {}
public void setTextAppearance(Context context, int resId) {}
public Locale getTextLocale() {
return null;
}
public LocaleList getTextLocales() {
return null;
}
public void setTextLocale(Locale locale) {}
public void setTextLocales(LocaleList locales) {}
public float getTextSize() {
return 0;
}
public float getScaledTextSize() {
return 0;
}
public int getTypefaceStyle() {
return 0;
}
public void setTextSize(float size) {}
public void setTextSize(int unit, float size) {}
public int getTextSizeUnit() {
return 0;
}
public float getTextScaleX() {
return 0;
}
public void setTextScaleX(float size) {}
public void setTypeface(Typeface tf) {}
public Typeface getTypeface() {
return null;
}
public void setElegantTextHeight(boolean elegant) {}
public void setFallbackLineSpacing(boolean enabled) {}
public boolean isFallbackLineSpacing() {
return false;
}
public boolean isElegantTextHeight() {
return false;
}
public float getLetterSpacing() {
return 0;
}
public void setLetterSpacing(float letterSpacing) {}
public String getFontFeatureSettings() {
return null;
}
public String getFontVariationSettings() {
return null;
}
public void setBreakStrategy(int breakStrategy) {}
public int getBreakStrategy() {
return 0;
}
public void setHyphenationFrequency(int hyphenationFrequency) {}
public int getHyphenationFrequency() {
return 0;
}
public void setJustificationMode(int justificationMode) {}
public int getJustificationMode() {
return 0;
}
public void setFontFeatureSettings(String fontFeatureSettings) {}
public boolean setFontVariationSettings(String fontVariationSettings) {
return false;
}
public void setTextColor(int color) {}
public void setTextColor(ColorStateList colors) {}
public final ColorStateList getTextColors() {
return null;
}
public final int getCurrentTextColor() {
return 0;
}
public void setHighlightColor(int color) {}
public int getHighlightColor() {
return 0;
}
public final void setShowSoftInputOnFocus(boolean show) {}
public final boolean getShowSoftInputOnFocus() {
return false;
}
public void setShadowLayer(float radius, float dx, float dy, int color) {}
public float getShadowRadius() {
return 0;
}
public float getShadowDx() {
return 0;
}
public float getShadowDy() {
return 0;
}
public int getShadowColor() {
return 0;
}
public final void setAutoLinkMask(int mask) {}
public final void setLinksClickable(boolean whether) {}
public final boolean getLinksClickable() {
return false;
}
public final void setHintTextColor(int color) {}
public final void setHintTextColor(ColorStateList colors) {}
public final ColorStateList getHintTextColors() {
return null;
}
public final int getCurrentHintTextColor() {
return 0;
}
public final void setLinkTextColor(int color) {}
public final void setLinkTextColor(ColorStateList colors) {}
public final ColorStateList getLinkTextColors() {
return null;
}
public void setGravity(int gravity) {}
public int getGravity() {
return 0;
}
public int getPaintFlags() {
return 0;
}
public void setPaintFlags(int flags) {}
public void setHorizontallyScrolling(boolean whether) {}
public final boolean isHorizontallyScrollable() {
return false;
}
public boolean getHorizontallyScrolling() {
return false;
}
public void setMinLines(int minLines) {}
public int getMinLines() {
return 0;
}
public void setMinHeight(int minPixels) {}
public int getMinHeight() {
return 0;
}
public void setMaxLines(int maxLines) {}
public int getMaxLines() {
return 0;
}
public void setMaxHeight(int maxPixels) {}
public int getMaxHeight() {
return 0;
}
public void setLines(int lines) {}
public void setHeight(int pixels) {}
public void setMinEms(int minEms) {}
public int getMinEms() {
return 0;
}
public void setMinWidth(int minPixels) {}
public int getMinWidth() {
return 0;
}
public void setMaxEms(int maxEms) {}
public int getMaxEms() {
return 0;
}
public void setMaxWidth(int maxPixels) {}
public int getMaxWidth() {
return 0;
}
public void setEms(int ems) {}
public void setWidth(int pixels) {}
public void setLineSpacing(float add, float mult) {}
public float getLineSpacingMultiplier() {
return 0;
}
public float getLineSpacingExtra() {
return 0;
}
public void setLineHeight(int lineHeight) {}
public final void append(CharSequence text) {}
public void append(CharSequence text, int start, int end) {}
public void setFreezesText(boolean freezesText) {}
public boolean getFreezesText() {
return false;
}
public final void setText(CharSequence text) {}
public final void setTextKeepState(CharSequence text) {}
public void setText(CharSequence text, BufferType type) {}
public final void setText(char[] text, int start, int len) {}
public final void setTextKeepState(CharSequence text, BufferType type) {}
public final void setText(int resid) {}
public final void setText(int resid, BufferType type) {}
public final void setHint(CharSequence hint) {}
public final void setHint(int resid) {}
public CharSequence getHint() {
return null;
}
public boolean isSingleLine() {
return false;
}
public void setInputType(int type) {}
public boolean isAnyPasswordInputType() {
return false;
}
public void setRawInputType(int type) {}
public int getInputType() {
return 0;
}
public void setImeOptions(int imeOptions) {}
public int getImeOptions() {
return 0;
}
public void setImeActionLabel(CharSequence label, int actionId) {}
public CharSequence getImeActionLabel() {
return null;
}
public int getImeActionId() {
return 0;
}
public void onEditorAction(int actionCode) {}
public void setPrivateImeOptions(String type) {}
public String getPrivateImeOptions() {
return null;
}
public Bundle getInputExtras(boolean create) {
return null;
}
public void setImeHintLocales(LocaleList hintLocales) {}
public LocaleList getImeHintLocales() {
return null;
}
public CharSequence getError() {
return null;
}
public void setError(CharSequence error) {}
public void setError(CharSequence error, Drawable icon) {}
public boolean isTextSelectable() {
return false;
}
public void setTextIsSelectable(boolean selectable) {}
public int getHorizontalOffsetForDrawables() {
return 0;
}
public int getLineCount() {
return 0;
}
public int getLineBounds(int line, Rect bounds) {
return 0;
}
public int getBaseline() {
return 0;
}
public void resetErrorChangedFlag() {}
public void hideErrorIfUnchanged() {}
public boolean onCheckIsTextEditor() {
return false;
}
public void beginBatchEdit() {}
public void endBatchEdit() {}
public void onBeginBatchEdit() {}
public void onEndBatchEdit() {}
public boolean onPrivateIMECommand(String action, Bundle data) {
return false;
}
public void nullLayouts() {}
public boolean useDynamicLayout() {
return false;
}
public void setIncludeFontPadding(boolean includepad) {}
public boolean getIncludeFontPadding() {
return false;
}
public boolean bringPointIntoView(int offset) {
return false;
}
public boolean moveCursorToVisibleOffset() {
return false;
}
public void computeScroll() {}
public void debug(int depth) {}
public int getSelectionStart() {
return 0;
}
public int getSelectionEnd() {
return 0;
}
public boolean hasSelection() {
return false;
}
public void setSingleLine() {}
public void setAllCaps(boolean allCaps) {}
public boolean isAllCaps() {
return false;
}
public void setSingleLine(boolean singleLine) {}
public void setMarqueeRepeatLimit(int marqueeLimit) {}
public int getMarqueeRepeatLimit() {
return 0;
}
public void setSelectAllOnFocus(boolean selectAllOnFocus) {}
public void setCursorVisible(boolean visible) {}
public boolean isCursorVisible() {
return false;
}
public void onWindowFocusChanged(boolean hasWindowFocus) {}
public void clearComposingText() {}
public void setSelected(boolean selected) {}
public boolean showContextMenu() {
return false;
}
public boolean showContextMenu(float x, float y) {
return false;
}
public boolean didTouchFocusSelect() {
return false;
}
public void cancelLongPress() {}
public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, int flags) {}
public enum BufferType {
}
public static ColorStateList getTextColors(Context context, TypedArray attrs) {
return null;
}
public static int getTextColor(Context context, TypedArray attrs, int def) {
return 0;
}
public final void setTextOperationUser(UserHandle user) {}
public Locale getTextServicesLocale() {
return null;
}
public boolean isInExtractedMode() {
return false;
}
public Locale getSpellCheckerLocale() {
return null;
}
public CharSequence getAccessibilityClassName() {
return null;
}
public boolean isPositionVisible(final float positionX, final float positionY) {
return false;
}
public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
return false;
}
public void sendAccessibilityEventInternal(int eventType) {}
public boolean isInputMethodTarget() {
return false;
}
public boolean onTextContextMenuItem(int id) {
return false;
}
public boolean performLongClick() {
return false;
}
public boolean isSuggestionsEnabled() {
return false;
}
public void hideFloatingToolbar(int durationMs) {}
public int getOffsetForPosition(float x, float y) {
return 0;
}
public void onRtlPropertiesChanged(int layoutDirection) {}
public void onResolveDrawables(int layoutDirection) {}
public CharSequence getIterableTextForAccessibility() {
return null;
}
public int getAccessibilitySelectionStart() {
return 0;
}
public boolean isAccessibilitySelectionExtendable() {
return false;
}
public int getAccessibilitySelectionEnd() {
return 0;
}
public void setAccessibilitySelection(int start, int end) {}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2018 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 androidx.activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.view.View;
public class ComponentActivity extends androidx.core.app.ComponentActivity {
public ComponentActivity() {}
public ComponentActivity(int contentLayoutId) {}
public final Object onRetainNonConfigurationInstance() {
return null;
}
public Object onRetainCustomNonConfigurationInstance() {
return null;
}
public Object getLastCustomNonConfigurationInstance() {
return null;
}
@Override
public void setContentView(int layoutResID) {}
@Override
public void setContentView(View view) {}
public Context peekAvailableContext() {
return null;
}
public void onBackPressed() {}
@Override
public void startActivityForResult(Intent intent, int requestCode) {}
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {}
public void startIntentSenderForResult(IntentSender intent, int requestCode, Intent fillInIntent,
int flagsMask, int flagsValues, int extraFlags) throws IntentSender.SendIntentException {}
public void startIntentSenderForResult(IntentSender intent, int requestCode, Intent fillInIntent,
int flagsMask, int flagsValues, int extraFlags, Bundle options)
throws IntentSender.SendIntentException {}
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {}
public void reportFullyDrawn() {}
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package androidx.core.app;
import android.app.Activity;
public class ComponentActivity extends Activity {
public void putExtraData(ExtraData extraData) {}
public <T extends ExtraData> T getExtraData(Class<T> extraDataClass) {
return null;
}
public static class ExtraData {
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright 2018 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 androidx.fragment.app;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.View;
import androidx.activity.ComponentActivity;
public class FragmentActivity extends ComponentActivity {
public FragmentActivity() {}
public FragmentActivity(int contentLayoutId) {}
public void supportFinishAfterTransition() {}
public void supportPostponeEnterTransition() {}
public void supportStartPostponedEnterTransition() {}
public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {}
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {}
public void onConfigurationChanged(Configuration newConfig) {}
public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
return null;
}
public View onCreateView(String name, Context context, AttributeSet attrs) {
return null;
}
public void onLowMemory() {}
public void onStateNotSaved() {}
public void supportInvalidateOptionsMenu() {}
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {}
public void onAttachFragment(Fragment fragment) {}
public FragmentManager getSupportFragmentManager() {
return null;
}
public final void validateRequestPermissionsRequestCode(int requestCode) {}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {}
public void startActivityFromFragment(Fragment fragment, Intent intent, int requestCode) {}
public void startActivityFromFragment(Fragment fragment, Intent intent, int requestCode,
Bundle options) {}
public void startIntentSenderFromFragment(Fragment fragment, IntentSender intent,
int requestCode, Intent fillInIntent, int flagsMask, int flagsValues,
int extraFlags, Bundle options) throws IntentSender.SendIntentException {}
}

View File

@@ -0,0 +1,160 @@
/*
* Copyright 2018 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 androidx.fragment.app;
import java.util.List;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
public abstract class FragmentManager {
public static void enableDebugLogging(boolean enabled) {}
public static boolean isLoggingEnabled(int level) {
return false;
}
public interface BackStackEntry {
int getId();
String getName();
int getBreadCrumbTitleRes();
int getBreadCrumbShortTitleRes();
CharSequence getBreadCrumbTitle();
CharSequence getBreadCrumbShortTitle();
}
public interface OnBackStackChangedListener {
void onBackStackChanged();
}
public abstract static class FragmentLifecycleCallbacks {
public void onFragmentPreAttached(FragmentManager fm, Fragment f, Context context) {}
public void onFragmentAttached(FragmentManager fm, Fragment f, Context context) {}
public void onFragmentPreCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) {}
public void onFragmentCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) {}
public void onFragmentActivityCreated(FragmentManager fm, Fragment f,
Bundle savedInstanceState) {}
public void onFragmentViewCreated(FragmentManager fm, Fragment f, View v,
Bundle savedInstanceState) {}
public void onFragmentStarted(FragmentManager fm, Fragment f) {}
public void onFragmentResumed(FragmentManager fm, Fragment f) {}
public void onFragmentPaused(FragmentManager fm, Fragment f) {}
public void onFragmentStopped(FragmentManager fm, Fragment f) {}
public void onFragmentSaveInstanceState(FragmentManager fm, Fragment f, Bundle outState) {}
public void onFragmentViewDestroyed(FragmentManager fm, Fragment f) {}
public void onFragmentDestroyed(FragmentManager fm, Fragment f) {}
public void onFragmentDetached(FragmentManager fm, Fragment f) {}
}
public FragmentTransaction openTransaction() {
return null;
}
public FragmentTransaction beginTransaction() {
return null;
}
public boolean executePendingTransactions() {
return false;
}
public void restoreBackStack(String name) {}
public void saveBackStack(String name) {}
public void popBackStack() {}
public boolean popBackStackImmediate() {
return false;
}
public void popBackStack(final String name, final int flags) {}
public boolean popBackStackImmediate(String name, int flags) {
return false;
}
public void popBackStack(final int id, final int flags) {}
public boolean popBackStackImmediate(int id, int flags) {
return false;
}
public int getBackStackEntryCount() {
return 0;
}
public BackStackEntry getBackStackEntryAt(int index) {
return null;
}
public void addOnBackStackChangedListener(OnBackStackChangedListener listener) {}
public void removeOnBackStackChangedListener(OnBackStackChangedListener listener) {}
public final void setFragmentResult(String requestKey, Bundle result) {}
public final void clearFragmentResult(String requestKey) {}
public final void clearFragmentResultListener(String requestKey) {}
public void putFragment(Bundle bundle, String key, Fragment fragment) {}
public Fragment getFragment(Bundle bundle, String key) {
return null;
}
public static <F extends Fragment> F findFragment(View view) {
return null;
}
public List<Fragment> getFragments() {
return null;
}
public Fragment.SavedState saveFragmentInstanceState(Fragment fragment) {
return null;
}
public boolean isDestroyed() {
return false;
}
@Override
public String toString() {
return null;
}
}

View File

@@ -0,0 +1,165 @@
/*
* Copyright 2018 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 androidx.fragment.app;
import android.app.Fragment;
import android.os.Bundle;
import android.view.View;
public abstract class FragmentTransaction {
public FragmentTransaction() {}
public final FragmentTransaction add(Class<? extends Fragment> fragmentClass, Bundle args,
String tag) {
return null;
}
public FragmentTransaction add(Fragment fragment, String tag) {
return null;
}
public final FragmentTransaction add(int containerViewId, Class<? extends Fragment> fragmentClass,
Bundle args) {
return null;
}
public FragmentTransaction add(int containerViewId, Fragment fragment) {
return null;
}
public final FragmentTransaction add(int containerViewId, Class<? extends Fragment> fragmentClass,
Bundle args, String tag) {
return null;
}
public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) {
return null;
}
public final FragmentTransaction replace(int containerViewId,
Class<? extends Fragment> fragmentClass, Bundle args) {
return null;
}
public FragmentTransaction replace(int containerViewId, Fragment fragment) {
return null;
}
public final FragmentTransaction replace(int containerViewId,
Class<? extends Fragment> fragmentClass, Bundle args, String tag) {
return null;
}
public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) {
return null;
}
public FragmentTransaction remove(Fragment fragment) {
return null;
}
public FragmentTransaction hide(Fragment fragment) {
return null;
}
public FragmentTransaction show(Fragment fragment) {
return null;
}
public FragmentTransaction detach(Fragment fragment) {
return null;
}
public FragmentTransaction attach(Fragment fragment) {
return null;
}
public FragmentTransaction setPrimaryNavigationFragment(Fragment fragment) {
return null;
}
public boolean isEmpty() {
return false;
}
public FragmentTransaction setCustomAnimations(int enter, int exit) {
return null;
}
public FragmentTransaction setCustomAnimations(int enter, int exit, int popEnter, int popExit) {
return null;
}
public FragmentTransaction addSharedElement(View sharedElement, String name) {
return null;
}
public FragmentTransaction setTransition(int transition) {
return null;
}
public FragmentTransaction setTransitionStyle(int styleRes) {
return null;
}
public FragmentTransaction addToBackStack(String name) {
return null;
}
public boolean isAddToBackStackAllowed() {
return false;
}
public FragmentTransaction disallowAddToBackStack() {
return null;
}
public FragmentTransaction setBreadCrumbTitle(int res) {
return null;
}
public FragmentTransaction setBreadCrumbTitle(CharSequence text) {
return null;
}
public FragmentTransaction setBreadCrumbShortTitle(int res) {
return null;
}
public FragmentTransaction setBreadCrumbShortTitle(CharSequence text) {
return null;
}
public FragmentTransaction setReorderingAllowed(boolean reorderingAllowed) {
return null;
}
public FragmentTransaction setAllowOptimization(boolean allowOptimization) {
return null;
}
public FragmentTransaction runOnCommit(Runnable runnable) {
return null;
}
public abstract int commit();
public abstract int commitAllowingStateLoss();
public abstract void commitNow();
public abstract void commitNowAllowingStateLoss();
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2018 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 androidx.security.crypto;
import android.content.Context;
import androidx.annotation.NonNull;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
public final class EncryptedFile {
public enum FileEncryptionScheme {
AES256_GCM_HKDF_4KB;
}
public static final class Builder {
public Builder(@NonNull File file, @NonNull Context context, @NonNull String masterKeyAlias,
@NonNull FileEncryptionScheme fileEncryptionScheme) {}
public Builder(@NonNull Context context, @NonNull File file, @NonNull MasterKey masterKey,
@NonNull FileEncryptionScheme fileEncryptionScheme) {}
public Builder setKeysetPrefName(@NonNull String keysetPrefName) {
return null;
}
public Builder setKeysetAlias(@NonNull String keysetAlias) {
return null;
}
public EncryptedFile build() throws GeneralSecurityException, IOException {
return null;
}
}
public FileOutputStream openFileOutput() throws GeneralSecurityException, IOException {
return null;
}
public FileInputStream openFileInput()
throws GeneralSecurityException, IOException, FileNotFoundException {
return null;
}
}