Merge "Remove ArcVideoBridge service from framework/base."
diff --git a/Android.bp b/Android.bp
index 3a5fcfa..ee593aa 100644
--- a/Android.bp
+++ b/Android.bp
@@ -506,11 +506,14 @@
"telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl",
"telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl",
"telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl",
+ "telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl",
"telephony/java/android/telephony/mbms/IDownloadStatusListener.aidl",
"telephony/java/android/telephony/mbms/IDownloadProgressListener.aidl",
"telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl",
+ "telephony/java/android/telephony/mbms/IGroupCallCallback.aidl",
"telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl",
"telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl",
+ "telephony/java/android/telephony/mbms/vendor/IMbmsGroupCallService.aidl",
"telephony/java/android/telephony/INetworkService.aidl",
"telephony/java/android/telephony/INetworkServiceCallback.aidl",
"telephony/java/com/android/ims/internal/IImsCallSession.aidl",
@@ -686,6 +689,7 @@
"android.hardware.vibrator-V1.2-java",
"android.hardware.wifi-V1.0-java-constants",
"android.hardware.radio-V1.0-java",
+ "android.hardware.radio-V1.3-java",
"android.hardware.usb.gadget-V1.0-java",
],
@@ -795,7 +799,7 @@
java_library {
name: "ext",
installable: true,
- no_framework_libs: true,
+ sdk_version: "core_current",
static_libs: [
"libphonenumber-platform",
"nist-sip",
@@ -1152,7 +1156,7 @@
previous_api: ":last-released-public-api",
merge_annotations_dirs: [
"metalava-manual",
- "ojluni-annotated-stubs",
+ "ojluni-annotated-sdk-stubs",
],
}
@@ -1214,7 +1218,12 @@
previous_api: ":last-released-public-api",
merge_annotations_dirs: [
"metalava-manual",
- "ojluni-annotated-stubs",
+ "ojluni-annotated-sdk-stubs",
+ ],
+ api_levels_annotations_enabled: true,
+ api_levels_annotations_dirs: [
+ "sdk-dir",
+ "api-versions-jars-dir",
],
}
@@ -1262,6 +1271,9 @@
}
droiddoc {
+ // Please sync with android-api-council@ before making any changes for the name property below.
+ // Since there's cron jobs that fetch offline-sdk-referenceonly-docs-docs.zip periodically.
+ // See b/116221385 for reference.
name: "offline-sdk-referenceonly-docs",
defaults: ["framework-docs-default"],
srcs: [
@@ -1278,6 +1290,9 @@
}
droiddoc {
+ // Please sync with android-api-council@ before making any changes for the name property below.
+ // Since there's cron jobs that fetch offline-system-sdk-referenceonly-docs-docs.zip periodically.
+ // See b/116221385 for reference.
name: "offline-system-sdk-referenceonly-docs",
defaults: ["framework-docs-default"],
srcs: [
@@ -1485,7 +1500,7 @@
previous_api: ":last-released-public-api",
merge_annotations_dirs: [
"metalava-manual",
- "ojluni-annotated-stubs",
+ "ojluni-annotated-sdk-stubs",
],
args: " --show-annotation android.annotation.SystemApi",
}
@@ -1571,6 +1586,7 @@
removed_api_file: "api/removed.txt",
},
},
+ jdiff_enabled: true,
}
droidstubs {
@@ -1595,6 +1611,7 @@
removed_api_file: "api/system-removed.txt",
},
},
+ jdiff_enabled: true,
}
droidstubs {
diff --git a/Android.mk b/Android.mk
index 5c4c237..d333074 100644
--- a/Android.mk
+++ b/Android.mk
@@ -53,265 +53,16 @@
cat $^ | sort -u > $@.tmp
$(call commit-change-for-toc,$@)
-# the documentation
-# ============================================================
-
-# TODO: deal with com/google/android/googleapps
-packages_to_document := \
- android \
- javax/microedition/khronos \
- org/apache/http/conn \
- org/apache/http/params \
-
-# include definition of libcore_to_document
-include libcore/Docs.mk
-
-non_base_dirs := \
- ../opt/telephony/src/java/android/telephony \
- ../opt/telephony/src/java/android/telephony/gsm \
- ../opt/net/voip/src/java/android/net/rtp \
- ../opt/net/voip/src/java/android/net/sip \
-
-# Find all files in specific directories (relative to frameworks/base)
-# to document and check apis
-files_to_check_apis := \
- $(call find-other-java-files, \
- $(non_base_dirs) \
- )
-
-# Find all files in specific packages that were used to compile
-# framework.jar to document and check apis
-files_to_check_apis += \
- $(addprefix ../../,\
- $(filter \
- $(foreach dir,$(FRAMEWORKS_BASE_JAVA_SRC_DIRS),\
- $(foreach package,$(packages_to_document),\
- $(dir)/$(package)/%.java)),\
- $(SOONG_FRAMEWORK_SRCS)))
-
-# Find all generated files that were used to compile framework.jar
-files_to_check_apis_generated := \
- $(filter $(OUT_DIR)/%,\
- $(SOONG_FRAMEWORK_SRCS))
-
-# These are relative to frameworks/base
-# FRAMEWORKS_BASE_SUBDIRS comes from build/core/pathmap.mk
-files_to_document := \
- $(files_to_check_apis) \
- $(call find-other-java-files,\
- test-base/src \
- test-mock/src \
- test-runner/src)
-
-# These are relative to frameworks/base
-html_dirs := \
- $(FRAMEWORKS_BASE_SUBDIRS) \
- $(non_base_dirs) \
-
-# Common sources for doc check and api check
-common_src_files := \
- $(call find-other-html-files, $(html_dirs)) \
- $(addprefix ../../, $(libcore_to_document)) \
-
-# These are relative to frameworks/base
-framework_docs_LOCAL_SRC_FILES := \
- $(files_to_document) \
- $(common_src_files) \
-
-# These are relative to frameworks/base
-framework_docs_LOCAL_API_CHECK_SRC_FILES := \
- $(files_to_check_apis) \
- $(common_src_files) \
-
# This is used by ide.mk as the list of source files that are
# always included.
INTERNAL_SDK_SOURCE_DIRS := $(addprefix $(LOCAL_PATH)/,$(dirs_to_document))
-framework_docs_LOCAL_DROIDDOC_SOURCE_PATH := \
- $(FRAMEWORKS_BASE_JAVA_SRC_DIRS)
-
-framework_docs_LOCAL_SRCJARS := $(SOONG_FRAMEWORK_SRCJARS)
-
-framework_docs_LOCAL_GENERATED_SOURCES := \
- $(libcore_to_document_generated) \
- $(files_to_check_apis_generated) \
-
-framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES := \
- core-oj \
- core-libart \
- conscrypt \
- bouncycastle \
- okhttp \
- ext \
- framework \
- voip-common \
-
-# Platform docs can refer to Support Library APIs, but we don't actually build
-# them as part of the docs target, so we need to include them on the classpath.
-framework_docs_LOCAL_JAVA_LIBRARIES := \
- $(framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES) \
- $(FRAMEWORKS_SUPPORT_JAVA_LIBRARIES)
-
-framework_docs_LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-framework_docs_LOCAL_DROIDDOC_HTML_DIR := docs/html
-# The since flag (-since N.xml API_LEVEL) is used to add API Level information
-# to the reference documentation. Must be in order of oldest to newest.
-#
-# Conscrypt (com.android.org.conscrypt) is an implementation detail and should
-# not be referenced in the documentation.
-framework_docs_LOCAL_DROIDDOC_OPTIONS := \
- -android \
- -knowntags ./frameworks/base/docs/knowntags.txt \
- -knowntags ./libcore/known_oj_tags.txt \
- -manifest ./frameworks/base/core/res/AndroidManifest.xml \
- -hidePackage com.android.internal \
- -hidePackage com.android.internal.util \
- -hidePackage com.android.okhttp \
- -hidePackage com.android.org.conscrypt \
- -hidePackage com.android.server
-
-# Convert an sdk level to a "since" argument.
-since-arg = -since $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/$(1)/public/api/android.$(2)) $(1)
-
-finalized_xml_sdks := $(call numerically_sort,\
- $(patsubst $(HISTORICAL_SDK_VERSIONS_ROOT)/%/public/api/android.xml,%,\
- $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/*/public/api/android.xml)))
-finalized_txt_sdks := $(call numerically_sort,\
- $(patsubst $(HISTORICAL_SDK_VERSIONS_ROOT)/%/public/api/android.txt,%,\
- $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/*/public/api/android.txt)))
-
-framework_docs_LOCAL_DROIDDOC_OPTIONS += $(foreach sdk,$(finalized_xml_sdks),$(call since-arg,$(sdk),xml))
-framework_docs_LOCAL_DROIDDOC_OPTIONS += $(foreach sdk,$(finalized_txt_sdks),$(call since-arg,$(sdk),txt))
-ifneq ($(PLATFORM_VERSION_CODENAME),REL)
- framework_docs_LOCAL_DROIDDOC_OPTIONS += \
- -since ./frameworks/base/api/current.txt $(PLATFORM_VERSION_CODENAME)
-endif
-framework_docs_LOCAL_DROIDDOC_OPTIONS += \
- -werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 \
- -overview $(LOCAL_PATH)/core/java/overview.html
-
-framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR:= \
- $(call intermediates-dir-for,JAVA_LIBRARIES,framework,,COMMON)
-
-framework_docs_LOCAL_ADDITIONAL_JAVA_DIR:= \
- $(framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR)
-
-framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES := \
- frameworks/base/docs/knowntags.txt \
- $(libcore_to_document_generated)
-
-samples_dir := development/samples/browseable
-
-# Whitelist of valid groups, used for default TOC grouping. Each sample must
-# belong to one (and only one) group. Assign samples to groups by setting
-# a sample.group var to one of these groups in the sample's _index.jd.
-sample_groups := -samplegroup Admin \
- -samplegroup Background \
- -samplegroup Connectivity \
- -samplegroup Content \
- -samplegroup Input \
- -samplegroup Media \
- -samplegroup Notification \
- -samplegroup RenderScript \
- -samplegroup Security \
- -samplegroup Sensors \
- -samplegroup System \
- -samplegroup Testing \
- -samplegroup UI \
- -samplegroup Views \
- -samplegroup Wearable
-
-## SDK version identifiers used in the published docs
- # major[.minor] version for current SDK. (full releases only)
-framework_docs_SDK_VERSION:=7.0
- # release version (ie "Release x") (full releases only)
-framework_docs_SDK_REL_ID:=1
-
-framework_docs_LOCAL_DROIDDOC_OPTIONS += \
- -hdf dac true \
- -hdf sdk.codename O \
- -hdf sdk.preview.version 1 \
- -hdf sdk.version $(framework_docs_SDK_VERSION) \
- -hdf sdk.rel.id $(framework_docs_SDK_REL_ID) \
- -hdf sdk.preview 0 \
- -resourcesdir $(LOCAL_PATH)/docs/html/reference/images/ \
- -resourcesoutdir reference/android/images/
-
-# Federate Support Library references against local API file.
-framework_docs_LOCAL_DROIDDOC_OPTIONS += \
- -federate SupportLib https://developer.android.com \
- -federationapi SupportLib prebuilts/sdk/current/support-api.txt
-
-# Federate AndroidX references against local API file.
-framework_docs_LOCAL_DROIDDOC_OPTIONS += \
- -federate AndroidX https://developer.android.com \
- -federationapi AndroidX prebuilts/sdk/current/androidx-api.txt
-
-# Get the highest numbered api txt for the given api level.
-# $(1): the api level (e.g. public, system)
-define highest_sdk_txt
-$(HISTORICAL_SDK_VERSIONS_ROOT)/$(lastword $(call numerically_sort, \
- $(patsubst \
- $(HISTORICAL_SDK_VERSIONS_ROOT)/%,\
- %,\
- $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/*/$(1)/api/android.txt)\
- ) \
-))
-endef
-
-# ==== Public API diff ===========================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(framework_docs_LOCAL_API_CHECK_SRC_FILES)
-LOCAL_GENERATED_SOURCES := $(framework_docs_LOCAL_GENERATED_SOURCES)
-LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
-LOCAL_JAVA_LIBRARIES := $(framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES)
-LOCAL_MODULE_CLASS := $(framework_docs_LOCAL_MODULE_CLASS)
-LOCAL_ADDITIONAL_JAVA_DIR := $(framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR)
-LOCAL_ADDITIONAL_DEPENDENCIES := \
- $(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES) \
- $(INTERNAL_PLATFORM_API_FILE)
-
-LOCAL_MODULE := offline-sdk-referenceonly
-
-# Basename, because apidiff adds .txt internally.
-LOCAL_APIDIFF_OLDAPI := $(basename $(call highest_sdk_txt,public))
-LOCAL_APIDIFF_NEWAPI := $(LOCAL_PATH)/../../$(basename $(INTERNAL_PLATFORM_API_FILE))
-
-include $(BUILD_APIDIFF)
-
-# Hack to get diffs included in docs output
-out_zip := $(OUT_DOCS)/$(LOCAL_MODULE)-docs.zip
-$(out_zip): $(full_target)
-
-# ==== System API diff ===========================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(framework_docs_LOCAL_API_CHECK_SRC_FILES)
-LOCAL_GENERATED_SOURCES := $(framework_docs_LOCAL_GENERATED_SOURCES)
-LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
-LOCAL_JAVA_LIBRARIES := $(framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES)
-LOCAL_MODULE_CLASS := $(framework_docs_LOCAL_MODULE_CLASS)
-LOCAL_ADDITIONAL_JAVA_DIR := $(framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR)
-LOCAL_ADDITIONAL_DEPENDENCIES := \
- $(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES) \
- $(INTERNAL_PLATFORM_SYSTEM_API_FILE)
-
-LOCAL_MODULE := offline-system-sdk-referenceonly
-
-# Basename, because apidiff adds .txt internally.
-LOCAL_APIDIFF_OLDAPI := $(basename $(call highest_sdk_txt,system))
-LOCAL_APIDIFF_NEWAPI := $(LOCAL_PATH)/../../$(basename $(INTERNAL_PLATFORM_SYSTEM_API_FILE))
-
-include $(BUILD_APIDIFF)
-
-# Hack to get diffs included in docs output
-out_zip := $(OUT_DOCS)/$(LOCAL_MODULE)-docs.zip
-$(out_zip): $(full_target)
-
$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_API_FILE))
$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_SYSTEM_API_FILE))
$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_TEST_API_FILE))
+$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_API_FILE):apistubs/android/public/api/android.txt)
+$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_SYSTEM_API_FILE):apistubs/android/system/api/android.txt)
+$(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_TEST_API_FILE):apistubs/android/test/api/android.txt)
# sdk.atree needs to copy the whole dir: $(OUT_DOCS)/offline-sdk to the final zip.
# So keep offline-sdk-timestamp target here, and unzip offline-sdk-docs.zip to
diff --git a/api/current.txt b/api/current.txt
index 2a1295c..bafd471 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -21,6 +21,7 @@
field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
field public static final java.lang.String BIND_AUTOFILL_SERVICE = "android.permission.BIND_AUTOFILL_SERVICE";
+ field public static final java.lang.String BIND_CALL_REDIRECTION_SERVICE = "android.permission.BIND_CALL_REDIRECTION_SERVICE";
field public static final deprecated java.lang.String BIND_CARRIER_MESSAGING_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_SERVICE";
field public static final java.lang.String BIND_CARRIER_SERVICES = "android.permission.BIND_CARRIER_SERVICES";
field public static final java.lang.String BIND_CHOOSER_TARGET_SERVICE = "android.permission.BIND_CHOOSER_TARGET_SERVICE";
@@ -7698,7 +7699,9 @@
method public boolean isMultipleAdvertisementSupported();
method public boolean isOffloadedFilteringSupported();
method public boolean isOffloadedScanBatchingSupported();
+ method public android.bluetooth.BluetoothServerSocket listenUsingInsecureL2capChannel() throws java.io.IOException;
method public android.bluetooth.BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(java.lang.String, java.util.UUID) throws java.io.IOException;
+ method public android.bluetooth.BluetoothServerSocket listenUsingL2capChannel() throws java.io.IOException;
method public android.bluetooth.BluetoothServerSocket listenUsingRfcommWithServiceRecord(java.lang.String, java.util.UUID) throws java.io.IOException;
method public boolean setName(java.lang.String);
method public boolean startDiscovery();
@@ -8066,7 +8069,9 @@
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int, android.os.Handler);
method public boolean createBond();
+ method public android.bluetooth.BluetoothSocket createInsecureL2capChannel(int) throws java.io.IOException;
method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
+ method public android.bluetooth.BluetoothSocket createL2capChannel(int) throws java.io.IOException;
method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
method public int describeContents();
method public boolean fetchUuidsWithSdp();
@@ -8482,6 +8487,7 @@
method public android.bluetooth.BluetoothSocket accept() throws java.io.IOException;
method public android.bluetooth.BluetoothSocket accept(int) throws java.io.IOException;
method public void close() throws java.io.IOException;
+ method public int getPsm();
}
public final class BluetoothSocket implements java.io.Closeable {
@@ -18481,6 +18487,114 @@
method public java.lang.CharSequence getName();
}
+ public class Bidi {
+ ctor public Bidi();
+ ctor public Bidi(int, int);
+ ctor public Bidi(java.lang.String, int);
+ ctor public Bidi(java.text.AttributedCharacterIterator);
+ ctor public Bidi(char[], int, byte[], int, int, int);
+ method public boolean baseIsLeftToRight();
+ method public int countParagraphs();
+ method public int countRuns();
+ method public android.icu.text.Bidi createLineBidi(int, int);
+ method public static byte getBaseDirection(java.lang.CharSequence);
+ method public int getBaseLevel();
+ method public android.icu.text.BidiClassifier getCustomClassifier();
+ method public int getCustomizedClass(int);
+ method public byte getDirection();
+ method public int getLength();
+ method public byte getLevelAt(int);
+ method public byte[] getLevels();
+ method public int getLogicalIndex(int);
+ method public int[] getLogicalMap();
+ method public android.icu.text.BidiRun getLogicalRun(int);
+ method public byte getParaLevel();
+ method public android.icu.text.BidiRun getParagraph(int);
+ method public android.icu.text.BidiRun getParagraphByIndex(int);
+ method public int getParagraphIndex(int);
+ method public int getProcessedLength();
+ method public int getReorderingMode();
+ method public int getReorderingOptions();
+ method public int getResultLength();
+ method public int getRunCount();
+ method public int getRunLevel(int);
+ method public int getRunLimit(int);
+ method public int getRunStart(int);
+ method public char[] getText();
+ method public java.lang.String getTextAsString();
+ method public int getVisualIndex(int);
+ method public int[] getVisualMap();
+ method public android.icu.text.BidiRun getVisualRun(int);
+ method public static int[] invertMap(int[]);
+ method public boolean isInverse();
+ method public boolean isLeftToRight();
+ method public boolean isMixed();
+ method public boolean isOrderParagraphsLTR();
+ method public boolean isRightToLeft();
+ method public void orderParagraphsLTR(boolean);
+ method public static int[] reorderLogical(byte[]);
+ method public static int[] reorderVisual(byte[]);
+ method public static void reorderVisually(byte[], int, java.lang.Object[], int, int);
+ method public static boolean requiresBidi(char[], int, int);
+ method public void setContext(java.lang.String, java.lang.String);
+ method public void setCustomClassifier(android.icu.text.BidiClassifier);
+ method public void setInverse(boolean);
+ method public android.icu.text.Bidi setLine(int, int);
+ method public void setPara(java.lang.String, byte, byte[]);
+ method public void setPara(char[], byte, byte[]);
+ method public void setPara(java.text.AttributedCharacterIterator);
+ method public void setReorderingMode(int);
+ method public void setReorderingOptions(int);
+ method public java.lang.String writeReordered(int);
+ method public static java.lang.String writeReverse(java.lang.String, int);
+ field public static final int DIRECTION_DEFAULT_LEFT_TO_RIGHT = 126; // 0x7e
+ field public static final int DIRECTION_DEFAULT_RIGHT_TO_LEFT = 127; // 0x7f
+ field public static final int DIRECTION_LEFT_TO_RIGHT = 0; // 0x0
+ field public static final int DIRECTION_RIGHT_TO_LEFT = 1; // 0x1
+ field public static final short DO_MIRRORING = 2; // 0x2
+ field public static final short INSERT_LRM_FOR_NUMERIC = 4; // 0x4
+ field public static final short KEEP_BASE_COMBINING = 1; // 0x1
+ field public static final byte LEVEL_DEFAULT_LTR = 126; // 0x7e
+ field public static final byte LEVEL_DEFAULT_RTL = 127; // 0x7f
+ field public static final byte LEVEL_OVERRIDE = -128; // 0xffffff80
+ field public static final byte LTR = 0; // 0x0
+ field public static final int MAP_NOWHERE = -1; // 0xffffffff
+ field public static final byte MAX_EXPLICIT_LEVEL = 125; // 0x7d
+ field public static final byte MIXED = 2; // 0x2
+ field public static final byte NEUTRAL = 3; // 0x3
+ field public static final int OPTION_DEFAULT = 0; // 0x0
+ field public static final int OPTION_INSERT_MARKS = 1; // 0x1
+ field public static final int OPTION_REMOVE_CONTROLS = 2; // 0x2
+ field public static final int OPTION_STREAMING = 4; // 0x4
+ field public static final short OUTPUT_REVERSE = 16; // 0x10
+ field public static final short REMOVE_BIDI_CONTROLS = 8; // 0x8
+ field public static final short REORDER_DEFAULT = 0; // 0x0
+ field public static final short REORDER_GROUP_NUMBERS_WITH_R = 2; // 0x2
+ field public static final short REORDER_INVERSE_FOR_NUMBERS_SPECIAL = 6; // 0x6
+ field public static final short REORDER_INVERSE_LIKE_DIRECT = 5; // 0x5
+ field public static final short REORDER_INVERSE_NUMBERS_AS_L = 4; // 0x4
+ field public static final short REORDER_NUMBERS_SPECIAL = 1; // 0x1
+ field public static final short REORDER_RUNS_ONLY = 3; // 0x3
+ field public static final byte RTL = 1; // 0x1
+ }
+
+ public class BidiClassifier {
+ ctor public BidiClassifier(java.lang.Object);
+ method public int classify(int);
+ method public java.lang.Object getContext();
+ method public void setContext(java.lang.Object);
+ }
+
+ public class BidiRun {
+ method public byte getDirection();
+ method public byte getEmbeddingLevel();
+ method public int getLength();
+ method public int getLimit();
+ method public int getStart();
+ method public boolean isEvenRun();
+ method public boolean isOddRun();
+ }
+
public abstract class BreakIterator implements java.lang.Cloneable {
ctor protected BreakIterator();
method public java.lang.Object clone();
@@ -18532,6 +18646,37 @@
field public static final int WORD_NUMBER_LIMIT = 200; // 0xc8
}
+ public abstract class CaseMap {
+ method public static android.icu.text.CaseMap.Fold fold();
+ method public abstract android.icu.text.CaseMap omitUnchangedText();
+ method public static android.icu.text.CaseMap.Lower toLower();
+ method public static android.icu.text.CaseMap.Title toTitle();
+ method public static android.icu.text.CaseMap.Upper toUpper();
+ }
+
+ public static final class CaseMap.Fold extends android.icu.text.CaseMap {
+ method public <A extends java.lang.Appendable> A apply(java.lang.CharSequence, A, android.icu.text.Edits);
+ method public android.icu.text.CaseMap.Fold omitUnchangedText();
+ method public android.icu.text.CaseMap.Fold turkic();
+ }
+
+ public static final class CaseMap.Lower extends android.icu.text.CaseMap {
+ method public <A extends java.lang.Appendable> A apply(java.util.Locale, java.lang.CharSequence, A, android.icu.text.Edits);
+ method public android.icu.text.CaseMap.Lower omitUnchangedText();
+ }
+
+ public static final class CaseMap.Title extends android.icu.text.CaseMap {
+ method public <A extends java.lang.Appendable> A apply(java.util.Locale, android.icu.text.BreakIterator, java.lang.CharSequence, A, android.icu.text.Edits);
+ method public android.icu.text.CaseMap.Title noBreakAdjustment();
+ method public android.icu.text.CaseMap.Title noLowercase();
+ method public android.icu.text.CaseMap.Title omitUnchangedText();
+ }
+
+ public static final class CaseMap.Upper extends android.icu.text.CaseMap {
+ method public <A extends java.lang.Appendable> A apply(java.util.Locale, java.lang.CharSequence, A, android.icu.text.Edits);
+ method public android.icu.text.CaseMap.Upper omitUnchangedText();
+ }
+
public final class CollationElementIterator {
method public int getMaxExpansion(int);
method public int getOffset();
@@ -19197,6 +19342,30 @@
enum_constant public static final android.icu.text.DisplayContext.Type SUBSTITUTE_HANDLING;
}
+ public final class Edits {
+ ctor public Edits();
+ method public void addReplace(int, int);
+ method public void addUnchanged(int);
+ method public android.icu.text.Edits.Iterator getCoarseChangesIterator();
+ method public android.icu.text.Edits.Iterator getCoarseIterator();
+ method public android.icu.text.Edits.Iterator getFineChangesIterator();
+ method public android.icu.text.Edits.Iterator getFineIterator();
+ method public boolean hasChanges();
+ method public int lengthDelta();
+ method public void reset();
+ }
+
+ public static final class Edits.Iterator {
+ method public int destinationIndex();
+ method public boolean findSourceIndex(int);
+ method public boolean hasChange();
+ method public int newLength();
+ method public boolean next();
+ method public int oldLength();
+ method public int replacementIndex();
+ method public int sourceIndex();
+ }
+
public abstract class IDNA {
method public static android.icu.text.IDNA getUTS46Instance(int);
method public abstract java.lang.StringBuilder labelToASCII(java.lang.CharSequence, java.lang.StringBuilder, android.icu.text.IDNA.Info);
@@ -26927,6 +27096,7 @@
method public android.net.Network[] getAllNetworks();
method public deprecated boolean getBackgroundDataSetting();
method public android.net.Network getBoundNetworkForProcess();
+ method public int getConnectionOwnerUid(int, java.net.InetSocketAddress, java.net.InetSocketAddress);
method public android.net.ProxyInfo getDefaultProxy();
method public android.net.LinkProperties getLinkProperties(android.net.Network);
method public int getMultipathPreference(android.net.Network);
@@ -33053,6 +33223,7 @@
method public static final void setThreadPriority(int) throws java.lang.IllegalArgumentException, java.lang.SecurityException;
method public static final deprecated boolean supportsProcesses();
field public static final int FIRST_APPLICATION_UID = 10000; // 0x2710
+ field public static final int INVALID_UID = -1; // 0xffffffff
field public static final int LAST_APPLICATION_UID = 19999; // 0x4e1f
field public static final int PHONE_UID = 1001; // 0x3e9
field public static final int SIGNAL_KILL = 9; // 0x9
@@ -40865,6 +41036,7 @@
field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 128; // 0x80
field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
+ field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 2048; // 0x800
field public static final int PROPERTY_RTT = 1024; // 0x400
field public static final int PROPERTY_SELF_MANAGED = 256; // 0x100
field public static final int PROPERTY_WIFI = 8; // 0x8
@@ -40902,8 +41074,9 @@
public abstract class CallRedirectionService extends android.app.Service {
ctor public CallRedirectionService();
method public final void cancelCall();
- method public android.os.IBinder onBind(android.content.Intent);
+ method public final android.os.IBinder onBind(android.content.Intent);
method public abstract void onPlaceCall(android.net.Uri, android.telecom.PhoneAccountHandle);
+ method public final boolean onUnbind(android.content.Intent);
method public final void placeCallUnmodified();
method public final void redirectCall(android.net.Uri, android.telecom.PhoneAccountHandle);
field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.CallRedirectionService";
@@ -41519,6 +41692,7 @@
field public static final java.lang.String EXTRA_CALL_BACK_NUMBER = "android.telecom.extra.CALL_BACK_NUMBER";
field public static final java.lang.String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE";
field public static final java.lang.String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecom.extra.CALL_DISCONNECT_MESSAGE";
+ field public static final java.lang.String EXTRA_CALL_NETWORK_TYPE = "android.telecom.extra.CALL_NETWORK_TYPE";
field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT";
field public static final java.lang.String EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME = "android.telecom.extra.CHANGE_DEFAULT_DIALER_PACKAGE_NAME";
field public static final java.lang.String EXTRA_INCOMING_CALL_ADDRESS = "android.telecom.extra.INCOMING_CALL_ADDRESS";
@@ -41816,6 +41990,7 @@
field public static final deprecated java.lang.String KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL = "restart_radio_on_pdp_fail_regular_deactivation_bool";
field public static final java.lang.String KEY_RTT_SUPPORTED_BOOL = "rtt_supported_bool";
field public static final java.lang.String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
+ field public static final java.lang.String KEY_SHOW_CALL_BLOCKING_DISABLED_NOTIFICATION_ALWAYS_BOOL = "show_call_blocking_disabled_notification_always_bool";
field public static final java.lang.String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
field public static final java.lang.String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
field public static final java.lang.String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
@@ -42077,6 +42252,13 @@
field public static final int STATUS_UNKNOWN = 0; // 0x0
}
+ public class MbmsGroupCallSession implements java.lang.AutoCloseable {
+ method public void close();
+ method public static android.telephony.MbmsGroupCallSession create(android.content.Context, java.util.concurrent.Executor, int, android.telephony.mbms.MbmsGroupCallSessionCallback);
+ method public static android.telephony.MbmsGroupCallSession create(android.content.Context, java.util.concurrent.Executor, android.telephony.mbms.MbmsGroupCallSessionCallback);
+ method public android.telephony.mbms.GroupCall startGroupCall(java.util.concurrent.Executor, long, int[], int[], android.telephony.mbms.GroupCallCallback);
+ }
+
public class MbmsStreamingSession implements java.lang.AutoCloseable {
method public void close();
method public static android.telephony.MbmsStreamingSession create(android.content.Context, java.util.concurrent.Executor, int, android.telephony.mbms.MbmsStreamingSessionCallback);
@@ -42085,7 +42267,7 @@
method public android.telephony.mbms.StreamingService startStreaming(android.telephony.mbms.StreamingServiceInfo, java.util.concurrent.Executor, android.telephony.mbms.StreamingServiceCallback);
}
- public class NeighboringCellInfo implements android.os.Parcelable {
+ public deprecated class NeighboringCellInfo implements android.os.Parcelable {
ctor public deprecated NeighboringCellInfo();
ctor public deprecated NeighboringCellInfo(int, int);
ctor public NeighboringCellInfo(int, java.lang.String, int);
@@ -42456,7 +42638,9 @@
method public static int getDefaultVoiceSubscriptionId();
method public static int[] getSubscriptionIds(int);
method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
+ method public boolean isActiveSubscriptionId(int);
method public boolean isNetworkRoaming(int);
+ method public static boolean isUsableSubscriptionId(int);
method public static boolean isValidSubscriptionId(int);
method public void removeOnOpportunisticSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
@@ -42470,6 +42654,7 @@
field public static final java.lang.String ACTION_REFRESH_SUBSCRIPTION_PLANS = "android.telephony.action.REFRESH_SUBSCRIPTION_PLANS";
field public static final int DATA_ROAMING_DISABLE = 0; // 0x0
field public static final int DATA_ROAMING_ENABLE = 1; // 0x1
+ field public static final int DEFAULT_SUBSCRIPTION_ID = 2147483647; // 0x7fffffff
field public static final java.lang.String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX";
field public static final int INVALID_SUBSCRIPTION_ID = -1; // 0xffffffff
}
@@ -42541,7 +42726,6 @@
method public java.lang.String getMmsUAProfUrl();
method public java.lang.String getMmsUserAgent();
method public java.lang.String getNai();
- method public deprecated java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
method public java.lang.String getNetworkCountryIso();
method public java.lang.String getNetworkOperator();
method public java.lang.String getNetworkOperatorName();
@@ -42843,6 +43027,36 @@
}
+package android.telephony.emergency {
+
+ public final class EmergencyNumber implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.lang.String getCountryIso();
+ method public int getEmergencyNumberSourceBitmask();
+ method public java.util.List<java.lang.Integer> getEmergencyNumberSources();
+ method public java.util.List<java.lang.Integer> getEmergencyServiceCategories();
+ method public int getEmergencyServiceCategoryBitmask();
+ method public java.lang.String getNumber();
+ method public boolean isFromSources(int);
+ method public boolean isInEmergencyServiceCategories(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.telephony.emergency.EmergencyNumber> CREATOR;
+ field public static final int EMERGENCY_NUMBER_SOURCE_DEFAULT = 8; // 0x8
+ field public static final int EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG = 4; // 0x4
+ field public static final int EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING = 1; // 0x1
+ field public static final int EMERGENCY_NUMBER_SOURCE_SIM = 2; // 0x2
+ field public static final int EMERGENCY_SERVICE_CATEGORY_AIEC = 64; // 0x40
+ field public static final int EMERGENCY_SERVICE_CATEGORY_AMBULANCE = 2; // 0x2
+ field public static final int EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE = 4; // 0x4
+ field public static final int EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD = 8; // 0x8
+ field public static final int EMERGENCY_SERVICE_CATEGORY_MIEC = 32; // 0x20
+ field public static final int EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE = 16; // 0x10
+ field public static final int EMERGENCY_SERVICE_CATEGORY_POLICE = 1; // 0x1
+ field public static final int EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED = 0; // 0x0
+ }
+
+}
+
package android.telephony.euicc {
public final class DownloadableSubscription implements android.os.Parcelable {
@@ -43022,6 +43236,29 @@
field public static final android.os.Parcelable.Creator<android.telephony.mbms.FileServiceInfo> CREATOR;
}
+ public class GroupCall implements java.lang.AutoCloseable {
+ method public void close();
+ method public long getTmgi();
+ method public void updateGroupCall(int[], int[]);
+ field public static final int REASON_BY_USER_REQUEST = 1; // 0x1
+ field public static final int REASON_FREQUENCY_CONFLICT = 3; // 0x3
+ field public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 6; // 0x6
+ field public static final int REASON_NONE = 0; // 0x0
+ field public static final int REASON_NOT_CONNECTED_TO_HOMECARRIER_LTE = 5; // 0x5
+ field public static final int REASON_OUT_OF_MEMORY = 4; // 0x4
+ field public static final int STATE_STALLED = 3; // 0x3
+ field public static final int STATE_STARTED = 2; // 0x2
+ field public static final int STATE_STOPPED = 1; // 0x1
+ }
+
+ public class GroupCallCallback {
+ ctor public GroupCallCallback();
+ method public void onBroadcastSignalStrengthUpdated(int);
+ method public void onError(int, java.lang.String);
+ method public void onGroupCallStateChanged(int, int);
+ field public static final int SIGNAL_STRENGTH_UNAVAILABLE = -1; // 0xffffffff
+ }
+
public class MbmsDownloadReceiver extends android.content.BroadcastReceiver {
ctor public MbmsDownloadReceiver();
method public void onReceive(android.content.Context, android.content.Intent);
@@ -43070,6 +43307,14 @@
field public static final int ERROR_UNABLE_TO_START_SERVICE = 302; // 0x12e
}
+ public class MbmsGroupCallSessionCallback {
+ ctor public MbmsGroupCallSessionCallback();
+ method public void onAvailableSaisUpdated(java.util.List<java.lang.Integer>, java.util.List<java.util.List<java.lang.Integer>>);
+ method public void onError(int, java.lang.String);
+ method public void onMiddlewareReady();
+ method public void onServiceInterfaceAvailable(java.lang.String, int);
+ }
+
public class MbmsStreamingSessionCallback {
ctor public MbmsStreamingSessionCallback();
method public void onError(int, java.lang.String);
@@ -54661,6 +54906,7 @@
public final class DelegateLastClassLoader extends dalvik.system.PathClassLoader {
ctor public DelegateLastClassLoader(java.lang.String, java.lang.ClassLoader);
ctor public DelegateLastClassLoader(java.lang.String, java.lang.String, java.lang.ClassLoader);
+ ctor public DelegateLastClassLoader(java.lang.String, java.lang.String, java.lang.ClassLoader, boolean);
}
public class DexClassLoader extends dalvik.system.BaseDexClassLoader {
diff --git a/api/removed.txt b/api/removed.txt
index f35348e..fba5187 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -540,6 +540,7 @@
}
public class TelephonyManager {
+ method public deprecated java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
method public deprecated android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, android.telephony.TelephonyScanManager.NetworkScanCallback);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 1df9a46..89ac721 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5048,6 +5048,7 @@
method public deprecated android.content.ComponentName getDefaultPhoneApp();
method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage();
method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsSupportingScheme(java.lang.String);
+ method public boolean isInEmergencyCall();
method public boolean isRinging();
method public boolean isTtySupported();
field public static final java.lang.String EXTRA_CALL_BACK_INTENT = "android.telecom.extra.CALL_BACK_INTENT";
@@ -5074,6 +5075,10 @@
field public static final java.lang.String MBMS_DOWNLOAD_SERVICE_ACTION = "android.telephony.action.EmbmsDownload";
}
+ public class MbmsGroupCallSession implements java.lang.AutoCloseable {
+ field public static final java.lang.String MBMS_GROUP_CALL_SERVICE_ACTION = "android.telephony.action.EmbmsGroupCall";
+ }
+
public class MbmsStreamingSession implements java.lang.AutoCloseable {
field public static final java.lang.String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming";
}
@@ -5133,9 +5138,12 @@
}
public class ServiceState implements android.os.Parcelable {
+ method public android.telephony.NetworkRegistrationState getNetworkRegistrationState(int, int);
method public java.util.List<android.telephony.NetworkRegistrationState> getNetworkRegistrationStates();
- method public java.util.List<android.telephony.NetworkRegistrationState> getNetworkRegistrationStates(int);
- method public android.telephony.NetworkRegistrationState getNetworkRegistrationStates(int, int);
+ method public deprecated java.util.List<android.telephony.NetworkRegistrationState> getNetworkRegistrationStates(int);
+ method public deprecated android.telephony.NetworkRegistrationState getNetworkRegistrationStates(int, int);
+ method public java.util.List<android.telephony.NetworkRegistrationState> getNetworkRegistrationStatesForDomain(int);
+ method public java.util.List<android.telephony.NetworkRegistrationState> getNetworkRegistrationStatesForTransportType(int);
}
public final class SmsManager {
@@ -5230,7 +5238,6 @@
}
public class TelephonyManager {
- method public deprecated void answerRingingCall();
method public deprecated void call(java.lang.String, java.lang.String);
method public int checkCarrierPrivilegesForPackage(java.lang.String);
method public int checkCarrierPrivilegesForPackageAnyPhone(java.lang.String);
@@ -5238,7 +5245,7 @@
method public boolean disableDataConnectivity();
method public boolean enableDataConnectivity();
method public void enableVideoCalling(boolean);
- method public deprecated boolean endCall();
+ method public java.lang.String getAidForAppType(int);
method public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
@@ -5253,6 +5260,8 @@
method public deprecated boolean getDataEnabled();
method public deprecated boolean getDataEnabled(int);
method public boolean getEmergencyCallbackMode();
+ method public java.lang.String getIsimDomain();
+ method public int getPreferredNetworkType(int);
method public int getSimApplicationState();
method public int getSimCardState();
method public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
@@ -5262,10 +5271,7 @@
method public boolean handlePinMmi(java.lang.String);
method public boolean handlePinMmiForSubscriber(int, java.lang.String);
method public boolean isDataConnectivityPossible();
- method public deprecated boolean isIdle();
- method public deprecated boolean isOffhook();
method public deprecated boolean isRadioOn();
- method public deprecated boolean isRinging();
method public boolean isVideoCallingEnabled();
method public deprecated boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
method public boolean needsOtaServiceProvisioning();
@@ -5279,7 +5285,6 @@
method public void setSimPowerStateForSlot(int, int);
method public deprecated void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
method public void setVoiceActivationState(int);
- method public deprecated void silenceRinger();
method public boolean supplyPin(java.lang.String);
method public int[] supplyPinReportResult(java.lang.String);
method public boolean supplyPuk(java.lang.String, java.lang.String);
@@ -5297,6 +5302,29 @@
field public static final java.lang.String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
field public static final java.lang.String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
field public static final java.lang.String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
+ field public static final int NETWORK_MODE_CDMA_EVDO = 4; // 0x4
+ field public static final int NETWORK_MODE_CDMA_NO_EVDO = 5; // 0x5
+ field public static final int NETWORK_MODE_EVDO_NO_CDMA = 6; // 0x6
+ field public static final int NETWORK_MODE_GLOBAL = 7; // 0x7
+ field public static final int NETWORK_MODE_GSM_ONLY = 1; // 0x1
+ field public static final int NETWORK_MODE_GSM_UMTS = 3; // 0x3
+ field public static final int NETWORK_MODE_LTE_CDMA_EVDO = 8; // 0x8
+ field public static final int NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA = 10; // 0xa
+ field public static final int NETWORK_MODE_LTE_GSM_WCDMA = 9; // 0x9
+ field public static final int NETWORK_MODE_LTE_ONLY = 11; // 0xb
+ field public static final int NETWORK_MODE_LTE_TDSCDMA = 15; // 0xf
+ field public static final int NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 22; // 0x16
+ field public static final int NETWORK_MODE_LTE_TDSCDMA_GSM = 17; // 0x11
+ field public static final int NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA = 20; // 0x14
+ field public static final int NETWORK_MODE_LTE_TDSCDMA_WCDMA = 19; // 0x13
+ field public static final int NETWORK_MODE_LTE_WCDMA = 12; // 0xc
+ field public static final int NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 21; // 0x15
+ field public static final int NETWORK_MODE_TDSCDMA_GSM = 16; // 0x10
+ field public static final int NETWORK_MODE_TDSCDMA_GSM_WCDMA = 18; // 0x12
+ field public static final int NETWORK_MODE_TDSCDMA_ONLY = 13; // 0xd
+ field public static final int NETWORK_MODE_TDSCDMA_WCDMA = 14; // 0xe
+ field public static final int NETWORK_MODE_WCDMA_ONLY = 2; // 0x2
+ field public static final int NETWORK_MODE_WCDMA_PREF = 0; // 0x0
field public static final int SIM_ACTIVATION_STATE_ACTIVATED = 2; // 0x2
field public static final int SIM_ACTIVATION_STATE_ACTIVATING = 1; // 0x1
field public static final int SIM_ACTIVATION_STATE_DEACTIVATED = 3; // 0x3
@@ -5632,6 +5660,7 @@
field public static final java.lang.String EXTRA_CODEC = "Codec";
field public static final java.lang.String EXTRA_DIALSTRING = "dialstring";
field public static final java.lang.String EXTRA_DISPLAY_TEXT = "DisplayText";
+ field public static final java.lang.String EXTRA_EMERGENCY_CALL = "e_call";
field public static final java.lang.String EXTRA_IS_CALL_PULL = "CallPull";
field public static final java.lang.String EXTRA_OI = "oi";
field public static final java.lang.String EXTRA_OIR = "oir";
@@ -6375,6 +6404,17 @@
method public int setTempFileRootDirectory(int, java.lang.String) throws android.os.RemoteException;
}
+ public class MbmsGroupCallServiceBase extends android.app.Service {
+ ctor public MbmsGroupCallServiceBase();
+ method public void dispose(int) throws android.os.RemoteException;
+ method public int initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int) throws android.os.RemoteException;
+ method public void onAppCallbackDied(int, int);
+ method public android.os.IBinder onBind(android.content.Intent);
+ method public int startGroupCall(int, long, int[], int[], android.telephony.mbms.GroupCallCallback);
+ method public void stopGroupCall(int, long);
+ method public void updateGroupCall(int, long, int[], int[]);
+ }
+
public class MbmsStreamingServiceBase extends android.os.Binder {
ctor public MbmsStreamingServiceBase();
method public void dispose(int) throws android.os.RemoteException;
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 961026b..72b60e2 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -143,3 +143,16 @@
}
+package android.telephony {
+
+ public class TelephonyManager {
+ method public deprecated void answerRingingCall();
+ method public deprecated boolean endCall();
+ method public deprecated boolean isIdle();
+ method public deprecated boolean isOffhook();
+ method public deprecated boolean isRinging();
+ method public deprecated void silenceRinger();
+ }
+
+}
+
diff --git a/api/test-current.txt b/api/test-current.txt
index 634293a..a7bb467 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -966,6 +966,10 @@
field public static final java.lang.String MBMS_DOWNLOAD_SERVICE_OVERRIDE_METADATA = "mbms-download-service-override";
}
+ public class MbmsGroupCallSession implements java.lang.AutoCloseable {
+ field public static final java.lang.String MBMS_GROUP_CALL_SERVICE_OVERRIDE_METADATA = "mbms-group-call-service-override";
+ }
+
public class MbmsStreamingSession implements java.lang.AutoCloseable {
field public static final java.lang.String MBMS_STREAMING_SERVICE_OVERRIDE_METADATA = "mbms-streaming-service-override";
}
@@ -1035,6 +1039,17 @@
method public int setTempFileRootDirectory(int, java.lang.String) throws android.os.RemoteException;
}
+ public class MbmsGroupCallServiceBase extends android.app.Service {
+ ctor public MbmsGroupCallServiceBase();
+ method public void dispose(int) throws android.os.RemoteException;
+ method public int initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int) throws android.os.RemoteException;
+ method public void onAppCallbackDied(int, int);
+ method public android.os.IBinder onBind(android.content.Intent);
+ method public int startGroupCall(int, long, int[], int[], android.telephony.mbms.GroupCallCallback);
+ method public void stopGroupCall(int, long);
+ method public void updateGroupCall(int, long, int[], int[]);
+ }
+
public class MbmsStreamingServiceBase extends android.os.Binder {
ctor public MbmsStreamingServiceBase();
method public void dispose(int) throws android.os.RemoteException;
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 4bbe042..72a4103 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -425,7 +425,19 @@
WorkerThreadSection::~WorkerThreadSection() {}
+void sigpipe_handler(int signum) {
+ if (signum == SIGPIPE) {
+ ALOGE("Wrote to a broken pipe\n");
+ } else {
+ ALOGE("Received unexpected signal: %d\n", signum);
+ }
+}
+
static void* worker_thread_func(void* cookie) {
+ // Don't crash the service if we write to a closed pipe (which can happen if
+ // dumping times out).
+ signal(SIGPIPE, sigpipe_handler);
+
WorkerThreadData* data = (WorkerThreadData*)cookie;
status_t err = data->section->BlockingCall(data->pipe.writeFd().get());
@@ -506,6 +518,7 @@
}
}
}
+
write_section_stats(requests->sectionStats(this->id), buffer);
if (timedOut || buffer.timedOut()) {
ALOGW("WorkerThreadSection '%s' timed out", this->name.string());
@@ -813,7 +826,10 @@
}
}
gLastLogsRetrieved[mLogID] = lastTimestamp;
- proto.flush(pipeWriteFd);
+ if (!proto.flush(pipeWriteFd) && errno == EPIPE) {
+ ALOGE("[%s] wrote to a broken pipe\n", this->name.string());
+ return EPIPE;
+ }
return NO_ERROR;
}
@@ -915,7 +931,7 @@
break;
}
if (cStatus != NO_ERROR) {
- ALOGE("TombstoneSection '%s' child had an issue: %s\n", this->name.string(), strerror(-cStatus));
+ ALOGE("[%s] child had an issue: %s\n", this->name.string(), strerror(-cStatus));
}
auto dump = std::make_unique<char[]>(buffer.size());
@@ -934,7 +950,13 @@
dumpPipe.readFd().reset();
}
- proto.flush(pipeWriteFd);
+ if (!proto.flush(pipeWriteFd) && errno == EPIPE) {
+ ALOGE("[%s] wrote to a broken pipe\n", this->name.string());
+ if (err != NO_ERROR) {
+ return EPIPE;
+ }
+ }
+
return err;
}
diff --git a/cmds/incidentd/src/Section.h b/cmds/incidentd/src/Section.h
index a031a15..2f89370 100644
--- a/cmds/incidentd/src/Section.h
+++ b/cmds/incidentd/src/Section.h
@@ -173,7 +173,7 @@
*/
class TombstoneSection : public WorkerThreadSection {
public:
- TombstoneSection(int id, const char* type, int64_t timeoutMs = 30000 /* 30 seconds */);
+ TombstoneSection(int id, const char* type, int64_t timeoutMs = 120000 /* 2 minutes */);
virtual ~TombstoneSection();
virtual status_t BlockingCall(int pipeWriteFd) const;
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index ab9c7e8..c4824c0 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -152,8 +152,9 @@
Temperature temperature = 10021;
}
- // DO NOT USE field numbers above 100,000 in AOSP. Field numbers above
- // 100,000 are reserved for non-AOSP (e.g. OEMs) to use.
+ // DO NOT USE field numbers above 100,000 in AOSP.
+ // Field numbers 100,000 - 199,999 are reserved for non-AOSP (e.g. OEMs) to use.
+ // Field numbers 200,000 and above are reserved for future use; do not use them at all.
}
/**
@@ -272,9 +273,9 @@
* Logs reporting of a ble scan finding results.
*
* Logged from:
- * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ * packages/apps/Bluetooth/src/com/android/bluetooth/gatt/AppScanStats.java
*/
-// TODO: Consider changing to tracking per-scanner-id (log from AppScanStats).
+// TODO: Consider also tracking per-scanner-id.
message BleScanResultReceived {
repeated AttributionNode attribution_node = 1;
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index fff909c..73ac968 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -489,6 +489,10 @@
{"AID_RESERVED_DISK", 1065},
{"AID_STATSD", 1066},
{"AID_INCIDENTD", 1067},
+ {"AID_SECURE_ELEMENT", 1068},
+ {"AID_LMKD", 1069},
+ {"AID_LLKD", 1070},
+ {"AID_IORAPD", 1071},
{"AID_SHELL", 2000},
{"AID_CACHE", 2001},
{"AID_DIAG", 2002}};
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index 3567605..9857cd0 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -11074,6 +11074,7 @@
HPLjava/lang/Long;->valueOf(Ljava/lang/String;I)Ljava/lang/Long;
HPLjava/lang/Math;->addExact(JJ)J
HPLjava/lang/Math;->scalb(FI)F
+HPLjava/lang/Object;->wait()V
HPLjava/lang/StackTraceElement;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V
HPLjava/lang/String;->copyValueOf([C)Ljava/lang/String;
HPLjava/lang/String;->join(Ljava/lang/CharSequence;[Ljava/lang/CharSequence;)Ljava/lang/String;
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index fcd1e4c..fbf5b52 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -2147,27 +2147,20 @@
Lcom/android/internal/telephony/ISub;->getDefaultSubId()I
Lcom/android/internal/telephony/ISub;->setDefaultDataSubId(I)V
Lcom/android/internal/telephony/ITelephony$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->endCall()Z
-Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->endCallForSubscriber(I)Z
Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->getDeviceId(Ljava/lang/String;)Ljava/lang/String;
Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->isRadioOn(Ljava/lang/String;)Z
Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->mRemote:Landroid/os/IBinder;
Lcom/android/internal/telephony/ITelephony$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ITelephony;
Lcom/android/internal/telephony/ITelephony$Stub;->DESCRIPTOR:Ljava/lang/String;
-Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_answerRingingCall:I
Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_call:I
Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_dial:I
-Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_endCall:I
Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_getDeviceId:I
-Lcom/android/internal/telephony/ITelephony;->answerRingingCall()V
Lcom/android/internal/telephony/ITelephony;->call(Ljava/lang/String;Ljava/lang/String;)V
Lcom/android/internal/telephony/ITelephony;->dial(Ljava/lang/String;)V
Lcom/android/internal/telephony/ITelephony;->disableDataConnectivity()Z
Lcom/android/internal/telephony/ITelephony;->disableLocationUpdates()V
Lcom/android/internal/telephony/ITelephony;->enableDataConnectivity()Z
Lcom/android/internal/telephony/ITelephony;->enableLocationUpdates()V
-Lcom/android/internal/telephony/ITelephony;->endCall()Z
-Lcom/android/internal/telephony/ITelephony;->endCallForSubscriber(I)Z
Lcom/android/internal/telephony/ITelephony;->getActivePhoneType()I
Lcom/android/internal/telephony/ITelephony;->getCallState()I
Lcom/android/internal/telephony/ITelephony;->getDataActivity()I
@@ -2179,12 +2172,8 @@
Lcom/android/internal/telephony/ITelephony;->hasIccCard()Z
Lcom/android/internal/telephony/ITelephony;->iccCloseLogicalChannel(II)Z
Lcom/android/internal/telephony/ITelephony;->iccTransmitApduLogicalChannel(IIIIIIILjava/lang/String;)Ljava/lang/String;
-Lcom/android/internal/telephony/ITelephony;->isIdle(Ljava/lang/String;)Z
-Lcom/android/internal/telephony/ITelephony;->isIdleForSubscriber(ILjava/lang/String;)Z
Lcom/android/internal/telephony/ITelephony;->isRadioOnForSubscriber(ILjava/lang/String;)Z
-Lcom/android/internal/telephony/ITelephony;->isRinging(Ljava/lang/String;)Z
Lcom/android/internal/telephony/ITelephony;->setRadio(Z)Z
-Lcom/android/internal/telephony/ITelephony;->silenceRinger()V
Lcom/android/internal/telephony/ITelephony;->supplyPin(Ljava/lang/String;)Z
Lcom/android/internal/telephony/ITelephony;->toggleRadioOnOff()V
Lcom/android/internal/telephony/ITelephony;->updateServiceLocation()V
@@ -2205,6 +2194,7 @@
Lcom/android/internal/telephony/SmsHeader$ConcatRef;-><init>()V
Lcom/android/internal/telephony/SmsHeader$PortAddrs;-><init>()V
Lcom/android/internal/telephony/SmsMessageBase;-><init>()V
+Lcom/android/internal/telephony/uicc/IccUtils;->bytesToHexString([B)Ljava/lang/String;
Lcom/android/internal/textservice/ITextServicesManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Lcom/android/internal/util/HexDump;->toHexString([BZ)Ljava/lang/String;
Lcom/android/internal/view/BaseIWindow;-><init>()V
@@ -2297,6 +2287,7 @@
Lcom/android/org/conscrypt/OpenSSLKey;->fromPrivateKey(Ljava/security/PrivateKey;)Lcom/android/org/conscrypt/OpenSSLKey;
Lcom/android/org/conscrypt/OpenSSLKey;->getNativeRef()Lcom/android/org/conscrypt/NativeRef$EVP_PKEY;
Lcom/android/org/conscrypt/OpenSSLKey;->getPublicKey()Ljava/security/PublicKey;
+Lcom/android/org/conscrypt/OpenSSLProvider;-><init>()V
Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getAlpnSelectedProtocol()[B
Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getChannelId()[B
Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getHostname()Ljava/lang/String;
@@ -2318,6 +2309,108 @@
Lcom/android/org/conscrypt/TrustedCertificateStore;->getCertificateChain(Ljava/security/cert/X509Certificate;)Ljava/util/List;
Lcom/android/org/conscrypt/TrustManagerImpl;-><init>(Ljava/security/KeyStore;)V
Lcom/android/org/conscrypt/TrustManagerImpl;->checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
+Lcom/google/android/mms/ContentType;->getAudioTypes()Ljava/util/ArrayList;
+Lcom/google/android/mms/ContentType;->getImageTypes()Ljava/util/ArrayList;
+Lcom/google/android/mms/ContentType;->getVideoTypes()Ljava/util/ArrayList;
+Lcom/google/android/mms/ContentType;->isAudioType(Ljava/lang/String;)Z
+Lcom/google/android/mms/ContentType;->isDrmType(Ljava/lang/String;)Z
+Lcom/google/android/mms/ContentType;->isImageType(Ljava/lang/String;)Z
+Lcom/google/android/mms/ContentType;->isTextType(Ljava/lang/String;)Z
+Lcom/google/android/mms/ContentType;->isVideoType(Ljava/lang/String;)Z
+Lcom/google/android/mms/MmsException;-><init>()V
+Lcom/google/android/mms/MmsException;-><init>(Ljava/lang/String;)V
+Lcom/google/android/mms/MmsException;-><init>(Ljava/lang/Throwable;)V
+Lcom/google/android/mms/pdu/AcknowledgeInd;-><init>(I[B)V
+Lcom/google/android/mms/pdu/CharacterSets;->getMimeName(I)Ljava/lang/String;
+Lcom/google/android/mms/pdu/DeliveryInd;->getMessageId()[B
+Lcom/google/android/mms/pdu/EncodedStringValue;-><init>(I[B)V
+Lcom/google/android/mms/pdu/EncodedStringValue;-><init>(Ljava/lang/String;)V
+Lcom/google/android/mms/pdu/EncodedStringValue;-><init>([B)V
+Lcom/google/android/mms/pdu/EncodedStringValue;->concat([Lcom/google/android/mms/pdu/EncodedStringValue;)Ljava/lang/String;
+Lcom/google/android/mms/pdu/EncodedStringValue;->encodeStrings([Ljava/lang/String;)[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/EncodedStringValue;->getString()Ljava/lang/String;
+Lcom/google/android/mms/pdu/GenericPdu;->getMessageType()I
+Lcom/google/android/mms/pdu/GenericPdu;->setFrom(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getBody()Lcom/google/android/mms/pdu/PduBody;
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getDate()J
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getPriority()I
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getSubject()Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getTo()[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setBody(Lcom/google/android/mms/pdu/PduBody;)V
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setDate(J)V
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setPriority(I)V
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setSubject(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/NotificationInd;->getContentLocation()[B
+Lcom/google/android/mms/pdu/NotificationInd;->getExpiry()J
+Lcom/google/android/mms/pdu/NotificationInd;->getFrom()Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/NotificationInd;->getMessageClass()[B
+Lcom/google/android/mms/pdu/NotificationInd;->getMessageSize()J
+Lcom/google/android/mms/pdu/NotificationInd;->getSubject()Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/NotificationInd;->getTransactionId()[B
+Lcom/google/android/mms/pdu/NotificationInd;->setContentLocation([B)V
+Lcom/google/android/mms/pdu/NotifyRespInd;-><init>(I[BI)V
+Lcom/google/android/mms/pdu/PduBody;-><init>()V
+Lcom/google/android/mms/pdu/PduBody;->addPart(ILcom/google/android/mms/pdu/PduPart;)V
+Lcom/google/android/mms/pdu/PduBody;->addPart(Lcom/google/android/mms/pdu/PduPart;)Z
+Lcom/google/android/mms/pdu/PduBody;->getPart(I)Lcom/google/android/mms/pdu/PduPart;
+Lcom/google/android/mms/pdu/PduBody;->getPartByContentId(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart;
+Lcom/google/android/mms/pdu/PduBody;->getPartByContentLocation(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart;
+Lcom/google/android/mms/pdu/PduBody;->getPartByFileName(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart;
+Lcom/google/android/mms/pdu/PduBody;->getPartByName(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart;
+Lcom/google/android/mms/pdu/PduBody;->getPartsNum()I
+Lcom/google/android/mms/pdu/PduComposer;-><init>(Landroid/content/Context;Lcom/google/android/mms/pdu/GenericPdu;)V
+Lcom/google/android/mms/pdu/PduComposer;->make()[B
+Lcom/google/android/mms/pdu/PduParser;->parse()Lcom/google/android/mms/pdu/GenericPdu;
+Lcom/google/android/mms/pdu/PduPart;-><init>()V
+Lcom/google/android/mms/pdu/PduPart;->generateLocation()Ljava/lang/String;
+Lcom/google/android/mms/pdu/PduPart;->getCharset()I
+Lcom/google/android/mms/pdu/PduPart;->getContentLocation()[B
+Lcom/google/android/mms/pdu/PduPart;->getContentType()[B
+Lcom/google/android/mms/pdu/PduPart;->getData()[B
+Lcom/google/android/mms/pdu/PduPart;->getDataUri()Landroid/net/Uri;
+Lcom/google/android/mms/pdu/PduPart;->getFilename()[B
+Lcom/google/android/mms/pdu/PduPart;->getName()[B
+Lcom/google/android/mms/pdu/PduPart;->setCharset(I)V
+Lcom/google/android/mms/pdu/PduPart;->setContentId([B)V
+Lcom/google/android/mms/pdu/PduPart;->setContentLocation([B)V
+Lcom/google/android/mms/pdu/PduPart;->setContentType([B)V
+Lcom/google/android/mms/pdu/PduPart;->setData([B)V
+Lcom/google/android/mms/pdu/PduPart;->setDataUri(Landroid/net/Uri;)V
+Lcom/google/android/mms/pdu/PduPersister;->getBytes(Ljava/lang/String;)[B
+Lcom/google/android/mms/pdu/PduPersister;->getPduPersister(Landroid/content/Context;)Lcom/google/android/mms/pdu/PduPersister;
+Lcom/google/android/mms/pdu/PduPersister;->getPendingMessages(J)Landroid/database/Cursor;
+Lcom/google/android/mms/pdu/PduPersister;->load(Landroid/net/Uri;)Lcom/google/android/mms/pdu/GenericPdu;
+Lcom/google/android/mms/pdu/PduPersister;->move(Landroid/net/Uri;Landroid/net/Uri;)Landroid/net/Uri;
+Lcom/google/android/mms/pdu/PduPersister;->persist(Lcom/google/android/mms/pdu/GenericPdu;Landroid/net/Uri;ZZLjava/util/HashMap;)Landroid/net/Uri;
+Lcom/google/android/mms/pdu/PduPersister;->persistPart(Lcom/google/android/mms/pdu/PduPart;JLjava/util/HashMap;)Landroid/net/Uri;
+Lcom/google/android/mms/pdu/PduPersister;->toIsoString([B)Ljava/lang/String;
+Lcom/google/android/mms/pdu/PduPersister;->updateHeaders(Landroid/net/Uri;Lcom/google/android/mms/pdu/SendReq;)V
+Lcom/google/android/mms/pdu/PduPersister;->updateParts(Landroid/net/Uri;Lcom/google/android/mms/pdu/PduBody;Ljava/util/HashMap;)V
+Lcom/google/android/mms/pdu/ReadOrigInd;->getMessageId()[B
+Lcom/google/android/mms/pdu/ReadRecInd;-><init>(Lcom/google/android/mms/pdu/EncodedStringValue;[BII[Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/ReadRecInd;->setDate(J)V
+Lcom/google/android/mms/pdu/RetrieveConf;->getFrom()Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/RetrieveConf;->getMessageId()[B
+Lcom/google/android/mms/pdu/RetrieveConf;->getTransactionId()[B
+Lcom/google/android/mms/pdu/SendConf;->getMessageId()[B
+Lcom/google/android/mms/pdu/SendConf;->getResponseStatus()I
+Lcom/google/android/mms/pdu/SendConf;->getTransactionId()[B
+Lcom/google/android/mms/pdu/SendReq;-><init>()V
+Lcom/google/android/mms/pdu/SendReq;->getBcc()[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/SendReq;->getTransactionId()[B
+Lcom/google/android/mms/pdu/SendReq;->setDeliveryReport(I)V
+Lcom/google/android/mms/pdu/SendReq;->setExpiry(J)V
+Lcom/google/android/mms/pdu/SendReq;->setMessageClass([B)V
+Lcom/google/android/mms/pdu/SendReq;->setMessageSize(J)V
+Lcom/google/android/mms/pdu/SendReq;->setReadReport(I)V
+Lcom/google/android/mms/pdu/SendReq;->setTo([Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/util/AbstractCache;->get(Ljava/lang/Object;)Ljava/lang/Object;
+Lcom/google/android/mms/util/PduCache;->getInstance()Lcom/google/android/mms/util/PduCache;
+Lcom/google/android/mms/util/PduCache;->isUpdating(Landroid/net/Uri;)Z
+Lcom/google/android/mms/util/PduCache;->purge(Landroid/net/Uri;)Lcom/google/android/mms/util/PduCacheEntry;
+Lcom/google/android/mms/util/PduCache;->purgeAll()V
+Lcom/google/android/mms/util/PduCacheEntry;->getPdu()Lcom/google/android/mms/pdu/GenericPdu;
+Lcom/google/android/mms/util/SqliteWrapper;->insert(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/content/ContentValues;)Landroid/net/Uri;
Ldalvik/system/BaseDexClassLoader;-><init>(Ljava/lang/String;Ljava/io/File;Ljava/lang/String;Ljava/lang/ClassLoader;Z)V
Ldalvik/system/BaseDexClassLoader;->addDexPath(Ljava/lang/String;)V
Ldalvik/system/BaseDexClassLoader;->addDexPath(Ljava/lang/String;Z)V
@@ -2621,6 +2714,7 @@
Ljava/net/SocketException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
Ljava/net/SocketImpl;->serverSocket:Ljava/net/ServerSocket;
Ljava/net/SocketImpl;->socket:Ljava/net/Socket;
+Ljava/net/SocksSocketImpl;-><init>()V
Ljava/net/URI;->fragment:Ljava/lang/String;
Ljava/net/URI;->host:Ljava/lang/String;
Ljava/net/URI;->port:I
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 50e97c5..d93befd 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -1436,6 +1436,12 @@
android.hardware.usb.UsbDeviceConnection
android.hardware.usb.UsbManager
android.hardware.usb.UsbRequest
+android.hidl.base.V1_0.DebugInfo
+android.hidl.base.V1_0.IBase
+android.hidl.manager.V1_0.IServiceManager
+android.hidl.manager.V1_0.IServiceManager$Proxy
+android.hidl.manager.V1_0.IServiceNotification
+android.hidl.manager.V1_0.IServiceNotification$Stub
android.icu.impl.BMPSet
android.icu.impl.CacheBase
android.icu.impl.CacheValue
@@ -2375,7 +2381,6 @@
android.os.-$$Lambda$StrictMode$yZJXPvy2veRNA-xL_SWdXzX_OLg
android.os.-$$Lambda$Trace$2zLZ-Lc2kAXsVjw_nLYeNhqmGq0
android.os.AsyncResult
-android.os.AsyncTask
android.os.AsyncTask$1
android.os.AsyncTask$2
android.os.AsyncTask$3
diff --git a/config/preloaded-classes-blacklist b/config/preloaded-classes-blacklist
index 8b8d640..eca3bf3 100644
--- a/config/preloaded-classes-blacklist
+++ b/config/preloaded-classes-blacklist
@@ -1,4 +1,5 @@
android.net.ConnectivityThread$Singleton
+android.os.AsyncTask
android.os.FileObserver
android.widget.Magnifier
sun.nio.fs.UnixChannelFactory
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 4c655b5..654bfaf 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -81,7 +81,8 @@
* {@link #getBondedDevices()}; start device discovery with
* {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
* listen for incoming RFComm connection requests with {@link
- * #listenUsingRfcommWithServiceRecord(String, UUID)}; or start a scan for
+ * #listenUsingRfcommWithServiceRecord(String, UUID)}; listen for incoming L2CAP Connection-oriented
+ * Channels (CoC) connection requests with {@link #listenUsingL2capChannel()}; or start a scan for
* Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
* </p>
* <p>This class is thread safe.</p>
@@ -2967,7 +2968,7 @@
/**
* Create a secure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
* assign a dynamic protocol/service multiplexer (PSM) value. This socket can be used to listen
- * for incoming connections.
+ * for incoming connections. The supported Bluetooth transport is LE only.
* <p>A remote device connecting to this socket will be authenticated and communication on this
* socket will be encrypted.
* <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
@@ -2977,21 +2978,16 @@
* closed, Bluetooth is turned off, or the application exits unexpectedly.
* <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
* defined and performed by the application.
- * <p>Use {@link BluetoothDevice#createL2capCocSocket(int, int)} to connect to this server
+ * <p>Use {@link BluetoothDevice#createL2capChannel(int)} to connect to this server
* socket from another Android device that is given the PSM value.
*
- * @param transport Bluetooth transport to use, must be {@link BluetoothDevice#TRANSPORT_LE}
* @return an L2CAP CoC BluetoothServerSocket
* @throws IOException on error, for example Bluetooth not available, or insufficient
* permissions, or unable to start this CoC
- * @hide
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
- public BluetoothServerSocket listenUsingL2capCoc(int transport)
+ public BluetoothServerSocket listenUsingL2capChannel()
throws IOException {
- if (transport != BluetoothDevice.TRANSPORT_LE) {
- throw new IllegalArgumentException("Unsupported transport: " + transport);
- }
BluetoothServerSocket socket =
new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, true, true,
SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
@@ -3005,7 +3001,7 @@
throw new IOException("Error: Unable to assign PSM value");
}
if (DBG) {
- Log.d(TAG, "listenUsingL2capCoc: set assigned PSM to "
+ Log.d(TAG, "listenUsingL2capChannel: set assigned PSM to "
+ assignedPsm);
}
socket.setChannel(assignedPsm);
@@ -3014,10 +3010,23 @@
}
/**
+ * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
+ * API name, listenUsingL2capChannel.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public BluetoothServerSocket listenUsingL2capCoc(int transport)
+ throws IOException {
+ Log.e(TAG, "listenUsingL2capCoc: PLEASE USE THE OFFICIAL API, listenUsingL2capChannel");
+ return listenUsingL2capChannel();
+ }
+
+ /**
* Create an insecure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
- * assign a dynamic PSM value. This socket can be used to listen for incoming connections.
+ * assign a dynamic PSM value. This socket can be used to listen for incoming connections. The
+ * supported Bluetooth transport is LE only.
* <p>The link key is not required to be authenticated, i.e the communication may be vulnerable
- * to man-in-the-middle attacks. Use {@link #listenUsingL2capCoc}, if an encrypted and
+ * to man-in-the-middle attacks. Use {@link #listenUsingL2capChannel}, if an encrypted and
* authenticated communication channel is desired.
* <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
* {@link BluetoothServerSocket}.
@@ -3027,21 +3036,16 @@
* unexpectedly.
* <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
* defined and performed by the application.
- * <p>Use {@link BluetoothDevice#createInsecureL2capCocSocket(int, int)} to connect to this
- * server socket from another Android device that is given the PSM value.
+ * <p>Use {@link BluetoothDevice#createInsecureL2capChannel(int)} to connect to this server
+ * socket from another Android device that is given the PSM value.
*
- * @param transport Bluetooth transport to use, must be {@link BluetoothDevice#TRANSPORT_LE}
* @return an L2CAP CoC BluetoothServerSocket
* @throws IOException on error, for example Bluetooth not available, or insufficient
* permissions, or unable to start this CoC
- * @hide
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
- public BluetoothServerSocket listenUsingInsecureL2capCoc(int transport)
+ public BluetoothServerSocket listenUsingInsecureL2capChannel()
throws IOException {
- if (transport != BluetoothDevice.TRANSPORT_LE) {
- throw new IllegalArgumentException("Unsupported transport: " + transport);
- }
BluetoothServerSocket socket =
new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, false, false,
SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
@@ -3055,11 +3059,24 @@
throw new IOException("Error: Unable to assign PSM value");
}
if (DBG) {
- Log.d(TAG, "listenUsingInsecureL2capOn: set assigned PSM to "
+ Log.d(TAG, "listenUsingInsecureL2capChannel: set assigned PSM to "
+ assignedPsm);
}
socket.setChannel(assignedPsm);
return socket;
}
+
+ /**
+ * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
+ * API name, listenUsingInsecureL2capChannel.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public BluetoothServerSocket listenUsingInsecureL2capCoc(int transport)
+ throws IOException {
+ Log.e(TAG, "listenUsingInsecureL2capCoc: PLEASE USE THE OFFICIAL API, "
+ + "listenUsingInsecureL2capChannel");
+ return listenUsingInsecureL2capChannel();
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 818a749..73e98cd 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1963,8 +1963,8 @@
/**
* Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can
* be used to start a secure outgoing connection to the remote device with the same dynamic
- * protocol/service multiplexer (PSM) value.
- * <p>This is designed to be used with {@link BluetoothAdapter#listenUsingL2capCoc(int)} for
+ * protocol/service multiplexer (PSM) value. The supported Bluetooth transport is LE only.
+ * <p>This is designed to be used with {@link BluetoothAdapter#listenUsingL2capChannel()} for
* peer-peer Bluetooth applications.
* <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection.
* <p>Application using this API is responsible for obtaining PSM value from remote device.
@@ -1975,59 +1975,71 @@
* secure socket connection is not possible, use {#link createInsecureLeL2capCocSocket(int,
* int)}.
*
- * @param transport Bluetooth transport to use, must be {@link #TRANSPORT_LE}
* @param psm dynamic PSM value from remote device
* @return a CoC #BluetoothSocket ready for an outgoing connection
* @throws IOException on error, for example Bluetooth not available, or insufficient
* permissions
- * @hide
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
- public BluetoothSocket createL2capCocSocket(int transport, int psm) throws IOException {
+ public BluetoothSocket createL2capChannel(int psm) throws IOException {
if (!isBluetoothEnabled()) {
- Log.e(TAG, "createL2capCocSocket: Bluetooth is not enabled");
+ Log.e(TAG, "createL2capChannel: Bluetooth is not enabled");
throw new IOException();
}
- if (transport != BluetoothDevice.TRANSPORT_LE) {
- throw new IllegalArgumentException("Unsupported transport: " + transport);
- }
- if (DBG) Log.d(TAG, "createL2capCocSocket: transport=" + transport + ", psm=" + psm);
+ if (DBG) Log.d(TAG, "createL2capChannel: psm=" + psm);
return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, true, true, this, psm,
null);
}
/**
+ * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
+ * API name, createL2capChannel.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public BluetoothSocket createL2capCocSocket(int transport, int psm) throws IOException {
+ Log.e(TAG, "createL2capCocSocket: PLEASE USE THE OFFICIAL API, createL2capChannel");
+ return createL2capChannel(psm);
+ }
+
+ /**
* Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can
* be used to start a secure outgoing connection to the remote device with the same dynamic
- * protocol/service multiplexer (PSM) value.
- * <p>This is designed to be used with {@link BluetoothAdapter#listenUsingInsecureL2capCoc(int)}
- * for peer-peer Bluetooth applications.
+ * protocol/service multiplexer (PSM) value. The supported Bluetooth transport is LE only.
+ * <p>This is designed to be used with {@link
+ * BluetoothAdapter#listenUsingInsecureL2capChannel()} for peer-peer Bluetooth applications.
* <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection.
* <p>Application using this API is responsible for obtaining PSM value from remote device.
* <p> The communication channel may not have an authenticated link key, i.e. it may be subject
- * to man-in-the-middle attacks. Use {@link #createL2capCocSocket(int, int)} if an encrypted and
+ * to man-in-the-middle attacks. Use {@link #createL2capChannel(int)} if an encrypted and
* authenticated communication channel is possible.
*
- * @param transport Bluetooth transport to use, must be {@link #TRANSPORT_LE}
* @param psm dynamic PSM value from remote device
* @return a CoC #BluetoothSocket ready for an outgoing connection
* @throws IOException on error, for example Bluetooth not available, or insufficient
* permissions
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public BluetoothSocket createInsecureL2capChannel(int psm) throws IOException {
+ if (!isBluetoothEnabled()) {
+ Log.e(TAG, "createInsecureL2capChannel: Bluetooth is not enabled");
+ throw new IOException();
+ }
+ if (DBG) {
+ Log.d(TAG, "createInsecureL2capChannel: psm=" + psm);
+ }
+ return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, false, false, this, psm,
+ null);
+ }
+
+ /**
+ * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
+ * API name, createInsecureL2capChannel.
* @hide
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
public BluetoothSocket createInsecureL2capCocSocket(int transport, int psm) throws IOException {
- if (!isBluetoothEnabled()) {
- Log.e(TAG, "createInsecureL2capCocSocket: Bluetooth is not enabled");
- throw new IOException();
- }
- if (transport != BluetoothDevice.TRANSPORT_LE) {
- throw new IllegalArgumentException("Unsupported transport: " + transport);
- }
- if (DBG) {
- Log.d(TAG, "createInsecureL2capCocSocket: transport=" + transport + ", psm=" + psm);
- }
- return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, false, false, this, psm,
- null);
+ Log.e(TAG, "createL2capCocSocket: PLEASE USE THE OFFICIAL API, createInsecureL2capChannel");
+ return createInsecureL2capChannel(psm);
}
}
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
index 183be5f..559a59b 100644
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -73,6 +73,8 @@
/** Connection canceled before completion. */
public static final int RESULT_CANCELED = 2;
+ private static final int UPLOADING_FEATURE_BITMASK = 0x08;
+
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
public void onBluetoothStateChange(boolean up) {
@@ -395,6 +397,23 @@
return false;
}
+ /**
+ * Returns the "Uploading" feature bit value from the SDP record's
+ * MapSupportedFeatures field (see Bluetooth MAP 1.4 spec, page 114).
+ * @param device The Bluetooth device to get this value for.
+ * @return Returns true if the Uploading bit value in SDP record's
+ * MapSupportedFeatures field is set. False is returned otherwise.
+ */
+ public boolean isUploadingSupported(BluetoothDevice device) {
+ try {
+ return (mService != null && isEnabled() && isValidDevice(device))
+ && ((mService.getSupportedFeatures(device) & UPLOADING_FEATURE_BITMASK) > 0);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.getMessage());
+ }
+ return false;
+ }
+
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index ba4b5a5..5fc344a 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -203,12 +203,11 @@
/**
* Returns the assigned dynamic protocol/service multiplexer (PSM) value for the listening L2CAP
* Connection-oriented Channel (CoC) server socket. This server socket must be returned by the
- * {#link BluetoothAdapter.listenUsingL2capCoc(int)} or {#link
- * BluetoothAdapter.listenUsingInsecureL2capCoc(int)}. The returned value is undefined if this
+ * {#link BluetoothAdapter.listenUsingL2capChannel()} or {#link
+ * BluetoothAdapter.listenUsingInsecureL2capChannel()}. The returned value is undefined if this
* method is called on non-L2CAP server sockets.
*
* @return the assigned PSM or LE_PSM value depending on transport
- * @hide
*/
public int getPsm() {
return mChannel;
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 780f896..3a1e2f5 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -667,6 +667,10 @@
* @return one of {@link #TYPE_RFCOMM}, {@link #TYPE_SCO} or {@link #TYPE_L2CAP}
*/
public int getConnectionType() {
+ if (mType == TYPE_L2CAP_LE) {
+ // Treat the LE CoC to be the same type as L2CAP.
+ return TYPE_L2CAP;
+ }
return mType;
}
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 212e132..7aa223c 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -124,7 +124,7 @@
*
* <p><strong>Data Authority</strong> matches if any of the given values match
* the Intent's data authority <em>and</em> one of the data schemes in the filter
- * has matched the Intent, <em>or</em> no authories were supplied in the filter.
+ * has matched the Intent, <em>or</em> no authorities were supplied in the filter.
* The Intent authority is determined by calling
* {@link Intent#getData} and {@link android.net.Uri#getAuthority} on that URI.
* <em>Note that authority matching here is <b>case sensitive</b>, unlike
diff --git a/core/java/android/net/ConnectionInfo.aidl b/core/java/android/net/ConnectionInfo.aidl
new file mode 100644
index 0000000..07faf8b
--- /dev/null
+++ b/core/java/android/net/ConnectionInfo.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright (C) 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 android.net;
+
+parcelable ConnectionInfo;
diff --git a/core/java/android/net/ConnectionInfo.java b/core/java/android/net/ConnectionInfo.java
new file mode 100644
index 0000000..58d0e05
--- /dev/null
+++ b/core/java/android/net/ConnectionInfo.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 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 android.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+
+/**
+ * Describe a network connection including local and remote address/port of a connection and the
+ * transport protocol.
+ *
+ * @hide
+ */
+public final class ConnectionInfo implements Parcelable {
+ public final int protocol;
+ public final InetSocketAddress local;
+ public final InetSocketAddress remote;
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public ConnectionInfo(int protocol, InetSocketAddress local, InetSocketAddress remote) {
+ this.protocol = protocol;
+ this.local = local;
+ this.remote = remote;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(protocol);
+ out.writeByteArray(local.getAddress().getAddress());
+ out.writeInt(local.getPort());
+ out.writeByteArray(remote.getAddress().getAddress());
+ out.writeInt(remote.getPort());
+ }
+
+ public static final Creator<ConnectionInfo> CREATOR = new Creator<ConnectionInfo>() {
+ public ConnectionInfo createFromParcel(Parcel in) {
+ int protocol = in.readInt();
+ InetAddress localAddress;
+ try {
+ localAddress = InetAddress.getByAddress(in.createByteArray());
+ } catch (UnknownHostException e) {
+ throw new IllegalArgumentException("Invalid InetAddress");
+ }
+ int localPort = in.readInt();
+ InetAddress remoteAddress;
+ try {
+ remoteAddress = InetAddress.getByAddress(in.createByteArray());
+ } catch (UnknownHostException e) {
+ throw new IllegalArgumentException("Invalid InetAddress");
+ }
+ int remotePort = in.readInt();
+ InetSocketAddress local = new InetSocketAddress(localAddress, localPort);
+ InetSocketAddress remote = new InetSocketAddress(remoteAddress, remotePort);
+ return new ConnectionInfo(protocol, local, remote);
+ }
+
+ public ConnectionInfo[] newArray(int size) {
+ return new ConnectionInfo[size];
+ }
+ };
+}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index ce18796..8333b81 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -26,7 +26,6 @@
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
@@ -59,6 +58,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.InetAddress;
+import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -3800,8 +3800,9 @@
private void unsupportedStartingFrom(int version) {
if (Process.myUid() == Process.SYSTEM_UID) {
- // The getApplicationInfo() call we make below is not supported in system context, and
- // we want to allow the system to use these APIs anyway.
+ // The getApplicationInfo() call we make below is not supported in system context. Let
+ // the call through here, and rely on the fact that ConnectivityService will refuse to
+ // allow the system to use these APIs anyway.
return;
}
@@ -3818,11 +3819,6 @@
// functions by accessing ConnectivityService directly. However, it should be clear that doing
// so is unsupported and may break in the future. http://b/22728205
private void checkLegacyRoutingApiAccess() {
- if (mContext.checkCallingOrSelfPermission("com.android.permission.INJECT_OMADM_SETTINGS")
- == PackageManager.PERMISSION_GRANTED) {
- return;
- }
-
unsupportedStartingFrom(VERSION_CODES.M);
}
@@ -3930,4 +3926,26 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Returns the {@code uid} of the owner of a network connection.
+ *
+ * @param protocol The protocol of the connection. Only {@code IPPROTO_TCP} and
+ * {@code IPPROTO_UDP} currently supported.
+ * @param local The local {@link InetSocketAddress} of a connection.
+ * @param remote The remote {@link InetSocketAddress} of a connection.
+ *
+ * @return {@code uid} if the connection is found and the app has permission to observe it
+ * (e.g., if it is associated with the calling VPN app's tunnel) or
+ * {@link android.os.Process#INVALID_UID} if the connection is not found.
+ */
+ public int getConnectionOwnerUid(int protocol, InetSocketAddress local,
+ InetSocketAddress remote) {
+ ConnectionInfo connectionInfo = new ConnectionInfo(protocol, local, remote);
+ try {
+ return mService.getConnectionOwnerUid(connectionInfo);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index ce95b60..e7d441d 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -17,6 +17,7 @@
package android.net;
import android.app.PendingIntent;
+import android.net.ConnectionInfo;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
@@ -182,4 +183,6 @@
String getCaptivePortalServerUrl();
byte[] getNetworkWatchlistConfigHash();
+
+ int getConnectionOwnerUid(in ConnectionInfo connectionInfo);
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 7ce7c92..d0cdf6e 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -40,6 +40,11 @@
public static final String SECONDARY_ZYGOTE_SOCKET = "zygote_secondary";
/**
+ * An invalid UID value.
+ */
+ public static final int INVALID_UID = -1;
+
+ /**
* Defines the root UID.
* @hide
*/
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 3e8e885..8492b0c 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -36,16 +36,12 @@
import android.view.Display;
import android.view.WindowManager;
-import com.android.internal.logging.MetricsLogger;
-
import libcore.io.Streams;
-import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
@@ -97,7 +93,7 @@
/** Used to communicate with recovery. See bootable/recovery/recovery.cpp. */
private static final File RECOVERY_DIR = new File("/cache/recovery");
private static final File LOG_FILE = new File(RECOVERY_DIR, "log");
- private static final File LAST_INSTALL_FILE = new File(RECOVERY_DIR, "last_install");
+ private static final String LAST_INSTALL_PATH = "last_install";
private static final String LAST_PREFIX = "last_";
private static final String ACTION_EUICC_FACTORY_RESET =
"com.android.internal.action.EUICC_FACTORY_RESET";
@@ -935,116 +931,6 @@
throw new IOException("Reboot failed (no permissions?)");
}
- // Read last_install; then report time (in seconds) and I/O (in MiB) for
- // this update to tron.
- // Only report on the reboots immediately after an OTA update.
- private static void parseLastInstallLog(Context context) {
- try (BufferedReader in = new BufferedReader(new FileReader(LAST_INSTALL_FILE))) {
- String line = null;
- int bytesWrittenInMiB = -1, bytesStashedInMiB = -1;
- int timeTotal = -1;
- int uncryptTime = -1;
- int sourceVersion = -1;
- int temperatureStart = -1;
- int temperatureEnd = -1;
- int temperatureMax = -1;
- int errorCode = -1;
- int causeCode = -1;
-
- while ((line = in.readLine()) != null) {
- // Here is an example of lines in last_install:
- // ...
- // time_total: 101
- // bytes_written_vendor: 51074
- // bytes_stashed_vendor: 200
- int numIndex = line.indexOf(':');
- if (numIndex == -1 || numIndex + 1 >= line.length()) {
- continue;
- }
- String numString = line.substring(numIndex + 1).trim();
- long parsedNum;
- try {
- parsedNum = Long.parseLong(numString);
- } catch (NumberFormatException ignored) {
- Log.e(TAG, "Failed to parse numbers in " + line);
- continue;
- }
-
- final int MiB = 1024 * 1024;
- int scaled;
- try {
- if (line.startsWith("bytes")) {
- scaled = Math.toIntExact(parsedNum / MiB);
- } else {
- scaled = Math.toIntExact(parsedNum);
- }
- } catch (ArithmeticException ignored) {
- Log.e(TAG, "Number overflows in " + line);
- continue;
- }
-
- if (line.startsWith("time")) {
- timeTotal = scaled;
- } else if (line.startsWith("uncrypt_time")) {
- uncryptTime = scaled;
- } else if (line.startsWith("source_build")) {
- sourceVersion = scaled;
- } else if (line.startsWith("bytes_written")) {
- bytesWrittenInMiB = (bytesWrittenInMiB == -1) ? scaled :
- bytesWrittenInMiB + scaled;
- } else if (line.startsWith("bytes_stashed")) {
- bytesStashedInMiB = (bytesStashedInMiB == -1) ? scaled :
- bytesStashedInMiB + scaled;
- } else if (line.startsWith("temperature_start")) {
- temperatureStart = scaled;
- } else if (line.startsWith("temperature_end")) {
- temperatureEnd = scaled;
- } else if (line.startsWith("temperature_max")) {
- temperatureMax = scaled;
- } else if (line.startsWith("error")) {
- errorCode = scaled;
- } else if (line.startsWith("cause")) {
- causeCode = scaled;
- }
- }
-
- // Don't report data to tron if corresponding entry isn't found in last_install.
- if (timeTotal != -1) {
- MetricsLogger.histogram(context, "ota_time_total", timeTotal);
- }
- if (uncryptTime != -1) {
- MetricsLogger.histogram(context, "ota_uncrypt_time", uncryptTime);
- }
- if (sourceVersion != -1) {
- MetricsLogger.histogram(context, "ota_source_version", sourceVersion);
- }
- if (bytesWrittenInMiB != -1) {
- MetricsLogger.histogram(context, "ota_written_in_MiBs", bytesWrittenInMiB);
- }
- if (bytesStashedInMiB != -1) {
- MetricsLogger.histogram(context, "ota_stashed_in_MiBs", bytesStashedInMiB);
- }
- if (temperatureStart != -1) {
- MetricsLogger.histogram(context, "ota_temperature_start", temperatureStart);
- }
- if (temperatureEnd != -1) {
- MetricsLogger.histogram(context, "ota_temperature_end", temperatureEnd);
- }
- if (temperatureMax != -1) {
- MetricsLogger.histogram(context, "ota_temperature_max", temperatureMax);
- }
- if (errorCode != -1) {
- MetricsLogger.histogram(context, "ota_non_ab_error_code", errorCode);
- }
- if (causeCode != -1) {
- MetricsLogger.histogram(context, "ota_non_ab_cause_code", causeCode);
- }
-
- } catch (IOException e) {
- Log.e(TAG, "Failed to read lines in last_install", e);
- }
- }
-
/**
* Called after booting to process and remove recovery-related files.
* @return the log file from recovery, or null if none was found.
@@ -1062,9 +948,6 @@
Log.e(TAG, "Error reading recovery log", e);
}
- if (log != null) {
- parseLastInstallLog(context);
- }
// Only remove the OTA package if it's partially processed (uncrypt'd).
boolean reservePackage = BLOCK_MAP_FILE.exists();
@@ -1095,7 +978,8 @@
// GmsCore to avoid re-downloading everything again.
String[] names = RECOVERY_DIR.list();
for (int i = 0; names != null && i < names.length; i++) {
- if (names[i].startsWith(LAST_PREFIX)) continue;
+ // Do not remove the last_install file since the recovery-persist takes care of it.
+ if (names[i].startsWith(LAST_PREFIX) || names[i].equals(LAST_INSTALL_PATH)) continue;
if (reservePackage && names[i].equals(BLOCK_MAP_FILE.getName())) continue;
if (reservePackage && names[i].equals(UNCRYPT_PACKAGE_FILE.getName())) continue;
diff --git a/core/java/android/preference/DialogPreference.java b/core/java/android/preference/DialogPreference.java
index 534ef8d..4b5a7b4 100644
--- a/core/java/android/preference/DialogPreference.java
+++ b/core/java/android/preference/DialogPreference.java
@@ -43,7 +43,7 @@
* A base class for {@link Preference} objects that are
* dialog-based. These preferences will, when clicked, open a dialog showing the
* actual preference controls.
- *
+ *
* @attr ref android.R.styleable#DialogPreference_dialogTitle
* @attr ref android.R.styleable#DialogPreference_dialogMessage
* @attr ref android.R.styleable#DialogPreference_dialogIcon
@@ -56,7 +56,7 @@
PreferenceManager.OnActivityDestroyListener {
@UnsupportedAppUsage
private AlertDialog.Builder mBuilder;
-
+
@UnsupportedAppUsage
private CharSequence mDialogTitle;
@UnsupportedAppUsage
@@ -77,6 +77,14 @@
@UnsupportedAppUsage
private int mWhichButtonClicked;
+ /** Dismiss the dialog on the UI thread, but not inline with handlers */
+ private final Runnable mDismissRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mDialog.dismiss();
+ }
+ };
+
public DialogPreference(
Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
@@ -112,7 +120,7 @@
/**
* Sets the title of the dialog. This will be shown on subsequent dialogs.
- *
+ *
* @param dialogTitle The title.
*/
public void setDialogTitle(CharSequence dialogTitle) {
@@ -126,7 +134,7 @@
public void setDialogTitle(int dialogTitleResId) {
setDialogTitle(getContext().getString(dialogTitleResId));
}
-
+
/**
* Returns the title to be shown on subsequent dialogs.
* @return The title.
@@ -134,7 +142,7 @@
public CharSequence getDialogTitle() {
return mDialogTitle;
}
-
+
/**
* Sets the message of the dialog. This will be shown on subsequent dialogs.
* <p>
@@ -142,7 +150,7 @@
* list-based dialogs, for example. If setting a custom View on a dialog via
* {@link #setDialogLayoutResource(int)}, include a text View with ID
* {@link android.R.id#message} and it will be populated with this message.
- *
+ *
* @param dialogMessage The message.
*/
public void setDialogMessage(CharSequence dialogMessage) {
@@ -156,7 +164,7 @@
public void setDialogMessage(int dialogMessageResId) {
setDialogMessage(getContext().getString(dialogMessageResId));
}
-
+
/**
* Returns the message to be shown on subsequent dialogs.
* @return The message.
@@ -164,26 +172,26 @@
public CharSequence getDialogMessage() {
return mDialogMessage;
}
-
+
/**
* Sets the icon of the dialog. This will be shown on subsequent dialogs.
- *
+ *
* @param dialogIcon The icon, as a {@link Drawable}.
*/
public void setDialogIcon(Drawable dialogIcon) {
mDialogIcon = dialogIcon;
}
-
+
/**
* Sets the icon (resource ID) of the dialog. This will be shown on
* subsequent dialogs.
- *
+ *
* @param dialogIconRes The icon, as a resource ID.
*/
public void setDialogIcon(@DrawableRes int dialogIconRes) {
mDialogIcon = getContext().getDrawable(dialogIconRes);
}
-
+
/**
* Returns the icon to be shown on subsequent dialogs.
* @return The icon, as a {@link Drawable}.
@@ -191,11 +199,11 @@
public Drawable getDialogIcon() {
return mDialogIcon;
}
-
+
/**
* Sets the text of the positive button of the dialog. This will be shown on
* subsequent dialogs.
- *
+ *
* @param positiveButtonText The text of the positive button.
*/
public void setPositiveButtonText(CharSequence positiveButtonText) {
@@ -209,27 +217,27 @@
public void setPositiveButtonText(@StringRes int positiveButtonTextResId) {
setPositiveButtonText(getContext().getString(positiveButtonTextResId));
}
-
+
/**
* Returns the text of the positive button to be shown on subsequent
* dialogs.
- *
+ *
* @return The text of the positive button.
*/
public CharSequence getPositiveButtonText() {
return mPositiveButtonText;
}
-
+
/**
* Sets the text of the negative button of the dialog. This will be shown on
* subsequent dialogs.
- *
+ *
* @param negativeButtonText The text of the negative button.
*/
public void setNegativeButtonText(CharSequence negativeButtonText) {
mNegativeButtonText = negativeButtonText;
}
-
+
/**
* @see #setNegativeButtonText(CharSequence)
* @param negativeButtonTextResId The negative button text as a resource.
@@ -237,38 +245,38 @@
public void setNegativeButtonText(@StringRes int negativeButtonTextResId) {
setNegativeButtonText(getContext().getString(negativeButtonTextResId));
}
-
+
/**
* Returns the text of the negative button to be shown on subsequent
* dialogs.
- *
+ *
* @return The text of the negative button.
*/
public CharSequence getNegativeButtonText() {
return mNegativeButtonText;
}
-
+
/**
* Sets the layout resource that is inflated as the {@link View} to be shown
* as the content View of subsequent dialogs.
- *
+ *
* @param dialogLayoutResId The layout resource ID to be inflated.
* @see #setDialogMessage(CharSequence)
*/
public void setDialogLayoutResource(int dialogLayoutResId) {
mDialogLayoutResId = dialogLayoutResId;
}
-
+
/**
* Returns the layout resource that is used as the content View for
* subsequent dialogs.
- *
+ *
* @return The layout resource.
*/
public int getDialogLayoutResource() {
return mDialogLayoutResId;
}
-
+
/**
* Prepares the dialog builder to be shown when the preference is clicked.
* Use this to set custom properties on the dialog.
@@ -278,7 +286,7 @@
*/
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
}
-
+
@Override
protected void onClick() {
if (mDialog != null && mDialog.isShowing()) return;
@@ -290,14 +298,14 @@
* Shows the dialog associated with this Preference. This is normally initiated
* automatically on clicking on the preference. Call this method if you need to
* show the dialog on some other event.
- *
+ *
* @param state Optional instance state to restore on the dialog
*/
protected void showDialog(Bundle state) {
Context context = getContext();
mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE;
-
+
mBuilder = new AlertDialog.Builder(context)
.setTitle(mDialogTitle)
.setIcon(mDialogIcon)
@@ -311,11 +319,11 @@
} else {
mBuilder.setMessage(mDialogMessage);
}
-
+
onPrepareDialogBuilder(mBuilder);
-
+
getPreferenceManager().registerOnActivityDestroyListener(this);
-
+
// Create the dialog
final Dialog dialog = mDialog = mBuilder.create();
if (state != null) {
@@ -324,10 +332,29 @@
if (needInputMethod()) {
requestInputMethod(dialog);
}
+ dialog.setOnShowListener(new DialogInterface.OnShowListener() {
+ @Override
+ public void onShow(DialogInterface dialog) {
+ removeDismissCallbacks();
+ }
+ });
dialog.setOnDismissListener(this);
dialog.show();
}
+ void postDismiss() {
+ removeDismissCallbacks();
+ View decorView = mDialog.getWindow().getDecorView();
+ decorView.post(mDismissRunnable);
+ }
+
+ private void removeDismissCallbacks() {
+ if (mDialog != null && mDialog.getWindow() != null
+ && mDialog.getWindow().getDecorView() != null) {
+ mDialog.getWindow().getDecorView().removeCallbacks(mDismissRunnable);
+ }
+ }
+
/**
* Returns whether the preference needs to display a soft input method when the dialog
* is displayed. Default is false. Subclasses should override this method if they need
@@ -350,7 +377,7 @@
* Creates the content view for the dialog (if a custom content view is
* required). By default, it inflates the dialog layout resource if it is
* set.
- *
+ *
* @return The content View for the dialog.
* @see #setLayoutResource(int)
*/
@@ -358,48 +385,49 @@
if (mDialogLayoutResId == 0) {
return null;
}
-
+
LayoutInflater inflater = LayoutInflater.from(mBuilder.getContext());
return inflater.inflate(mDialogLayoutResId, null);
}
-
+
/**
* Binds views in the content View of the dialog to data.
* <p>
* Make sure to call through to the superclass implementation.
- *
+ *
* @param view The content View of the dialog, if it is custom.
*/
@CallSuper
protected void onBindDialogView(View view) {
View dialogMessageView = view.findViewById(com.android.internal.R.id.message);
-
+
if (dialogMessageView != null) {
final CharSequence message = getDialogMessage();
int newVisibility = View.GONE;
-
+
if (!TextUtils.isEmpty(message)) {
if (dialogMessageView instanceof TextView) {
((TextView) dialogMessageView).setText(message);
}
-
+
newVisibility = View.VISIBLE;
}
-
+
if (dialogMessageView.getVisibility() != newVisibility) {
dialogMessageView.setVisibility(newVisibility);
}
}
}
-
+
public void onClick(DialogInterface dialog, int which) {
mWhichButtonClicked = which;
}
-
+
+ @Override
public void onDismiss(DialogInterface dialog) {
-
+ removeDismissCallbacks();
getPreferenceManager().unregisterOnActivityDestroyListener(this);
-
+
mDialog = null;
onDialogClosed(mWhichButtonClicked == DialogInterface.BUTTON_POSITIVE);
}
@@ -407,7 +435,7 @@
/**
* Called when the dialog is dismissed and should be used to save data to
* the {@link SharedPreferences}.
- *
+ *
* @param positiveResult Whether the positive button was clicked (true), or
* the negative button was clicked or the dialog was canceled (false).
*/
@@ -416,7 +444,7 @@
/**
* Gets the dialog that is shown by this preference.
- *
+ *
* @return The dialog, or null if a dialog is not being shown.
*/
public Dialog getDialog() {
@@ -427,11 +455,11 @@
* {@inheritDoc}
*/
public void onActivityDestroy() {
-
+
if (mDialog == null || !mDialog.isShowing()) {
return;
}
-
+
mDialog.dismiss();
}
@@ -466,7 +494,7 @@
private static class SavedState extends BaseSavedState {
boolean isDialogShowing;
Bundle dialogBundle;
-
+
public SavedState(Parcel source) {
super(source);
isDialogShowing = source.readInt() == 1;
@@ -495,5 +523,5 @@
}
};
}
-
+
}
diff --git a/core/java/android/preference/ListPreference.java b/core/java/android/preference/ListPreference.java
index e7dec0e..c0c71af 100644
--- a/core/java/android/preference/ListPreference.java
+++ b/core/java/android/preference/ListPreference.java
@@ -33,7 +33,7 @@
* <p>
* This preference will store a string into the SharedPreferences. This string will be the value
* from the {@link #setEntryValues(CharSequence[])} array.
- *
+ *
* @attr ref android.R.styleable#ListPreference_entries
* @attr ref android.R.styleable#ListPreference_entryValues
*/
@@ -193,7 +193,7 @@
/**
* Sets the value to the given index from the entry values.
- *
+ *
* @param index The index of the value to set.
*/
public void setValueIndex(int index) {
@@ -201,30 +201,30 @@
setValue(mEntryValues[index].toString());
}
}
-
+
/**
* Returns the value of the key. This should be one of the entries in
* {@link #getEntryValues()}.
- *
+ *
* @return The value of the key.
*/
public String getValue() {
- return mValue;
+ return mValue;
}
-
+
/**
* Returns the entry corresponding to the current value.
- *
+ *
* @return The entry corresponding to the current value, or null.
*/
public CharSequence getEntry() {
int index = getValueIndex();
return index >= 0 && mEntries != null ? mEntries[index] : null;
}
-
+
/**
* Returns the index of the given value (in the entry values array).
- *
+ *
* @param value The value whose index should be returned.
* @return The index of the value, or -1 if not found.
*/
@@ -238,22 +238,22 @@
}
return -1;
}
-
+
private int getValueIndex() {
return findIndexOfValue(mValue);
}
-
+
@Override
protected void onPrepareDialogBuilder(Builder builder) {
super.onPrepareDialogBuilder(builder);
-
+
if (mEntries == null || mEntryValues == null) {
throw new IllegalStateException(
"ListPreference requires an entries array and an entryValues array.");
}
mClickedDialogEntryIndex = getValueIndex();
- builder.setSingleChoiceItems(mEntries, mClickedDialogEntryIndex,
+ builder.setSingleChoiceItems(mEntries, mClickedDialogEntryIndex,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mClickedDialogEntryIndex = which;
@@ -263,10 +263,10 @@
* click, and dismisses the dialog.
*/
ListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
- dialog.dismiss();
+ postDismiss();
}
});
-
+
/*
* The typical interaction for list-based dialogs is to have
* click-on-an-item dismiss the dialog instead of the user having to
@@ -278,7 +278,7 @@
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
-
+
if (positiveResult && mClickedDialogEntryIndex >= 0 && mEntryValues != null) {
String value = mEntryValues[mClickedDialogEntryIndex].toString();
if (callChangeListener(value)) {
@@ -296,7 +296,7 @@
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
setValue(restoreValue ? getPersistedString(mValue) : (String) defaultValue);
}
-
+
@Override
protected Parcelable onSaveInstanceState() {
final Parcelable superState = super.onSaveInstanceState();
@@ -304,7 +304,7 @@
// No need to save instance state since it's persistent
return superState;
}
-
+
final SavedState myState = new SavedState(superState);
myState.value = getValue();
return myState;
@@ -317,15 +317,15 @@
super.onRestoreInstanceState(state);
return;
}
-
+
SavedState myState = (SavedState) state;
super.onRestoreInstanceState(myState.getSuperState());
setValue(myState.value);
}
-
+
private static class SavedState extends BaseSavedState {
String value;
-
+
public SavedState(Parcel source) {
super(source);
value = source.readString();
@@ -352,5 +352,5 @@
}
};
}
-
+
}
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 149f2b4..dd011a0 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -1444,18 +1444,6 @@
}
public static final class Media implements AudioColumns {
-
- private static final String[] EXTERNAL_PATHS;
-
- static {
- String secondary_storage = System.getenv("SECONDARY_STORAGE");
- if (secondary_storage != null) {
- EXTERNAL_PATHS = secondary_storage.split(":");
- } else {
- EXTERNAL_PATHS = new String[0];
- }
- }
-
/**
* Get the content:// style URI for the audio media table on the
* given volume.
@@ -1469,14 +1457,9 @@
}
public static Uri getContentUriForPath(String path) {
- for (String ep : EXTERNAL_PATHS) {
- if (path.startsWith(ep)) {
- return EXTERNAL_CONTENT_URI;
- }
- }
-
- return (path.startsWith(Environment.getExternalStorageDirectory().getPath()) ?
- EXTERNAL_CONTENT_URI : INTERNAL_CONTENT_URI);
+ return (path.startsWith(
+ Environment.getStorageDirectory().getAbsolutePath() + "/")
+ ? EXTERNAL_CONTENT_URI : INTERNAL_CONTENT_URI);
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4b76ba8..7370029 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7299,6 +7299,15 @@
public static final String DIALER_DEFAULT_APPLICATION = "dialer_default_application";
/**
+ * Specifies the package name currently configured to be the default application to perform
+ * the user-defined call redirection service with Telecom.
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public static final String CALL_REDIRECTION_DEFAULT_APPLICATION =
+ "call_redirection_default_application";
+
+ /**
* Specifies the package name currently configured to be the emergency assistance application
*
* @see android.telephony.TelephonyManager#ACTION_EMERGENCY_ASSISTANCE
@@ -9131,6 +9140,19 @@
public static final String MOBILE_DATA_ALWAYS_ON = "mobile_data_always_on";
/**
+ * Whether the wifi data connection should remain active even when higher
+ * priority networks like Ethernet are active, to keep both networks.
+ * In the case where higher priority networks are connected, wifi will be
+ * unused unless an application explicitly requests to use it.
+ *
+ * See ConnectivityService for more info.
+ *
+ * (0 = disabled, 1 = enabled)
+ * @hide
+ */
+ public static final String WIFI_ALWAYS_REQUESTED = "wifi_always_requested";
+
+ /**
* Size of the event buffer for IP connectivity metrics.
* @hide
*/
@@ -9469,8 +9491,7 @@
* Use the old dnsmasq DHCP server for tethering instead of the framework implementation.
*
* Integer values are interpreted as boolean, and the absence of an explicit setting
- * is interpreted as |true|.
- * TODO: make the default |false|
+ * is interpreted as |false|.
* @hide
*/
public static final String TETHER_ENABLE_LEGACY_DHCP_SERVER =
diff --git a/core/java/android/security/net/config/DirectoryCertificateSource.java b/core/java/android/security/net/config/DirectoryCertificateSource.java
index 119f5d0..4f4d62a 100644
--- a/core/java/android/security/net/config/DirectoryCertificateSource.java
+++ b/core/java/android/security/net/config/DirectoryCertificateSource.java
@@ -16,26 +16,23 @@
package android.security.net.config;
-import android.os.Environment;
-import android.os.UserHandle;
import android.util.ArraySet;
import android.util.Log;
-import android.util.Pair;
+
+import libcore.io.IoUtils;
+
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
-import java.io.InputStream;
import java.io.IOException;
-import java.security.cert.Certificate;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.Set;
-import libcore.io.IoUtils;
-
-import com.android.org.conscrypt.Hex;
-import com.android.org.conscrypt.NativeCrypto;
import javax.security.auth.x500.X500Principal;
@@ -192,8 +189,36 @@
}
private String getHash(X500Principal name) {
- int hash = NativeCrypto.X509_NAME_hash_old(name);
- return Hex.intToHexString(hash, 8);
+ int hash = hashName(name);
+ return intToHexString(hash, 8);
+ }
+
+ private static final char[] DIGITS = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+ private static String intToHexString(int i, int minWidth) {
+ int bufLen = 8; // Max number of hex digits in an int
+ char[] buf = new char[bufLen];
+ int cursor = bufLen;
+
+ do {
+ buf[--cursor] = DIGITS[i & 0xf];
+ } while ((i >>>= 4) != 0 || (bufLen - cursor < minWidth));
+
+ return new String(buf, cursor, bufLen - cursor);
+ }
+
+ // This code matches the code in X509_NAME_hash_old() in Conscrypt, which in turn matches
+ // the names of certificate files. It must be kept in sync.
+ private static int hashName(X500Principal principal) {
+ try {
+ byte[] digest = MessageDigest.getInstance("MD5").digest(principal.getEncoded());
+ int offset = 0;
+ return (((digest[offset++] & 0xff) << 0) | ((digest[offset++] & 0xff) << 8)
+ | ((digest[offset++] & 0xff) << 16) | ((digest[offset] & 0xff) << 24));
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ }
}
private X509Certificate readCertificate(String file) {
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index b93afdf..bca2e11 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1421,6 +1421,10 @@
mServedView.getWindowToken() == appWindowToken) {
finishInputLocked();
}
+ if (mCurRootView != null &&
+ mCurRootView.getWindowToken() == appWindowToken) {
+ mCurRootView = null;
+ }
}
}
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index b591163..f90eab1 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -236,6 +236,7 @@
displayName = FileUtils.buildValidFatFilename(displayName);
final File before = getFileForDocId(docId);
+ final File beforeVisibleFile = getFileForDocId(docId, true);
final File after = FileUtils.buildUniqueFile(before.getParentFile(), displayName);
if (!before.renameTo(after)) {
throw new IllegalStateException("Failed to rename to " + after);
@@ -245,7 +246,6 @@
onDocIdChanged(docId);
onDocIdChanged(afterDocId);
- final File beforeVisibleFile = getFileForDocId(docId, true);
final File afterVisibleFile = getFileForDocId(afterDocId, true);
moveInMediaStore(beforeVisibleFile, afterVisibleFile);
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index c388148..fee8345 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -171,8 +171,7 @@
boolean debuggable);
private native static int nativeCopyNativeBinaries(long handle, String sharedLibraryPath,
- String abiToCopy, boolean extractNativeLibs, boolean hasNativeBridge,
- boolean debuggable);
+ String abiToCopy, boolean extractNativeLibs, boolean debuggable);
private static long sumNativeBinaries(Handle handle, String abi) {
long sum = 0;
@@ -193,7 +192,7 @@
public static int copyNativeBinaries(Handle handle, File sharedLibraryDir, String abi) {
for (long apkHandle : handle.apkHandles) {
int res = nativeCopyNativeBinaries(apkHandle, sharedLibraryDir.getPath(), abi,
- handle.extractNativeLibs, HAS_NATIVE_BRIDGE, handle.debuggable);
+ handle.extractNativeLibs, handle.debuggable);
if (res != INSTALL_SUCCEEDED) {
return res;
}
@@ -448,9 +447,6 @@
// We don't care about the other return values for now.
private static final int BITCODE_PRESENT = 1;
- private static final boolean HAS_NATIVE_BRIDGE =
- !"0".equals(SystemProperties.get("ro.dalvik.vm.native.bridge", "0"));
-
private static native int hasRenderscriptBitcode(long apkHandle);
public static boolean hasRenderscriptBitcode(Handle handle) throws IOException {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 94c3933..10c32a3 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -5800,8 +5800,6 @@
for (int i = 0; i < N; i++) {
int uid = mapUid(ws.get(i));
getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
- StatsLog.write_non_chained(StatsLog.BLE_SCAN_RESULT_RECEIVED, ws.get(i), ws.getName(i),
- numNewResults);
}
final List<WorkChain> workChains = ws.getWorkChains();
@@ -5810,8 +5808,6 @@
final WorkChain wc = workChains.get(i);
int uid = mapUid(wc.getAttributionUid());
getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
- StatsLog.write(StatsLog.BLE_SCAN_RESULT_RECEIVED,
- wc.getUids(), wc.getTags(), numNewResults);
}
}
}
diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java
index 7fd83bc..f6d80a5 100644
--- a/core/java/com/android/internal/util/DumpUtils.java
+++ b/core/java/com/android/internal/util/DumpUtils.java
@@ -34,9 +34,18 @@
/**
* Helper functions for dumping the state of system services.
* Test:
- atest /android/pi-dev/frameworks/base/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
+ atest FrameworksCoreTests:DumpUtilsTest
*/
public final class DumpUtils {
+
+ /**
+ * List of component names that should be dumped in the bug report critical section.
+ *
+ * @hide
+ */
+ public static final ComponentName[] CRITICAL_SECTION_COMPONENTS = {
+ new ComponentName("com.android.systemui", "com.android.systemui.SystemUIService")
+ };
private static final String TAG = "DumpUtils";
private static final boolean DEBUG = false;
@@ -213,6 +222,45 @@
}
/**
+ * Return whether a package should be dumped in the critical section.
+ */
+ private static boolean isCriticalPackage(@Nullable ComponentName cname) {
+ if (cname == null) {
+ return false;
+ }
+
+ for (int i = 0; i < CRITICAL_SECTION_COMPONENTS.length; i++) {
+ if (cname.equals(CRITICAL_SECTION_COMPONENTS[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return whether a package name is considered to be part of the platform and in the critical
+ * section.
+ *
+ * @hide
+ */
+ public static boolean isPlatformCriticalPackage(@Nullable ComponentName.WithComponentName wcn) {
+ return (wcn != null) && isPlatformPackage(wcn.getComponentName()) &&
+ isCriticalPackage(wcn.getComponentName());
+ }
+
+ /**
+ * Return whether a package name is considered to be part of the platform but not in the the
+ * critical section.
+ *
+ * @hide
+ */
+ public static boolean isPlatformNonCriticalPackage(
+ @Nullable ComponentName.WithComponentName wcn) {
+ return (wcn != null) && isPlatformPackage(wcn.getComponentName()) &&
+ !isCriticalPackage(wcn.getComponentName());
+ }
+
+ /**
* Used for dumping providers and services. Return a predicate for a given filter string.
* @hide
*/
@@ -238,6 +286,16 @@
return DumpUtils::isNonPlatformPackage;
}
+ // Dump all platform-critical?
+ if ("all-platform-critical".equals(filterString)) {
+ return DumpUtils::isPlatformCriticalPackage;
+ }
+
+ // Dump all platform-non-critical?
+ if ("all-platform-non-critical".equals(filterString)) {
+ return DumpUtils::isPlatformNonCriticalPackage;
+ }
+
// Is the filter a component name? If so, do an exact match.
final ComponentName filterCname = ComponentName.unflattenFromString(filterString);
if (filterCname != null) {
diff --git a/core/jni/android_net_LocalSocketImpl.cpp b/core/jni/android_net_LocalSocketImpl.cpp
index 6df23f7..a1f2377 100644
--- a/core/jni/android_net_LocalSocketImpl.cpp
+++ b/core/jni/android_net_LocalSocketImpl.cpp
@@ -58,6 +58,11 @@
int ret;
int fd;
+ if (name == NULL) {
+ jniThrowNullPointerException(env, NULL);
+ return;
+ }
+
fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
if (env->ExceptionCheck()) {
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index dc04269..5eefc81 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -176,7 +176,6 @@
void** args = reinterpret_cast<void**>(arg);
jstring* javaNativeLibPath = (jstring*) args[0];
jboolean extractNativeLibs = *(jboolean*) args[1];
- jboolean hasNativeBridge = *(jboolean*) args[2];
ScopedUtfChars nativeLibPath(env, *javaNativeLibPath);
@@ -206,9 +205,7 @@
return INSTALL_FAILED_INVALID_APK;
}
- if (!hasNativeBridge) {
- return INSTALL_SUCCEEDED;
- }
+ return INSTALL_SUCCEEDED;
}
// Build local file path
@@ -489,9 +486,9 @@
static jint
com_android_internal_content_NativeLibraryHelper_copyNativeBinaries(JNIEnv *env, jclass clazz,
jlong apkHandle, jstring javaNativeLibPath, jstring javaCpuAbi,
- jboolean extractNativeLibs, jboolean hasNativeBridge, jboolean debuggable)
+ jboolean extractNativeLibs, jboolean debuggable)
{
- void* args[] = { &javaNativeLibPath, &extractNativeLibs, &hasNativeBridge };
+ void* args[] = { &javaNativeLibPath, &extractNativeLibs };
return (jint) iterateOverNativeFiles(env, apkHandle, javaCpuAbi, debuggable,
copyFileIfChanged, reinterpret_cast<void*>(args));
}
@@ -597,7 +594,7 @@
"(J)V",
(void *)com_android_internal_content_NativeLibraryHelper_close},
{"nativeCopyNativeBinaries",
- "(JLjava/lang/String;Ljava/lang/String;ZZZ)I",
+ "(JLjava/lang/String;Ljava/lang/String;ZZ)I",
(void *)com_android_internal_content_NativeLibraryHelper_copyNativeBinaries},
{"nativeSumNativeBinaries",
"(JLjava/lang/String;Z)J",
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
index c15b7ee..109e65c 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
@@ -285,10 +285,6 @@
static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path,
jint limitUid, jobjectArray limitIfacesObj, jint limitTag,
jboolean useBpfStats) {
- ScopedUtfChars path8(env, path);
- if (path8.c_str() == NULL) {
- return -1;
- }
std::vector<std::string> limitIfaces;
if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
@@ -308,6 +304,11 @@
if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0)
return -1;
} else {
+ ScopedUtfChars path8(env, path);
+ if (path8.c_str() == NULL) {
+ ALOGE("the qtaguid legacy path is invalid: %s", path8.c_str());
+ return -1;
+ }
if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag,
limitUid, path8.c_str()) < 0)
return -1;
diff --git a/core/proto/OWNERS b/core/proto/OWNERS
index ed42e2e..30a9a01 100644
--- a/core/proto/OWNERS
+++ b/core/proto/OWNERS
@@ -7,6 +7,8 @@
joeo@google.com
kwekua@google.com
singhtejinder@google.com
+yanglu@google.com
+yaochen@google.com
# Frameworks
ogunwale@google.com
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ac9617c..73bb1fc 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1827,6 +1827,13 @@
<permission android:name="android.permission.BIND_SCREENING_SERVICE"
android:protectionLevel="signature|privileged" />
+ <!-- Must be required by a {@link android.telecom.CallRedirectionService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature|privileged
+ -->
+ <permission android:name="android.permission.BIND_CALL_REDIRECTION_SERVICE"
+ android:protectionLevel="signature|privileged" />
+
<!-- Must be required by a {@link android.telecom.ConnectionService},
to ensure that only the system can bind to it.
@deprecated {@link android.telecom.ConnectionService}s should require
diff --git a/core/res/res/values-mcc262-mnc02/strings.xml b/core/res/res/values-mcc262-mnc02/strings.xml
deleted file mode 100644
index 2b89401..0000000
--- a/core/res/res/values-mcc262-mnc02/strings.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2017, Google Inc.
- *
- * 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.
- */
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- Do not translate. Template for showing mobile network operator name while WFC is active -->
- <string-array name="wfcSpnFormats">
- <item>%s</item>
- <item>%s Wi-Fi Calling</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-mcc302-mnc370/strings.xml b/core/res/res/values-mcc302-mnc370/strings.xml
deleted file mode 100644
index f5b8496..0000000
--- a/core/res/res/values-mcc302-mnc370/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2017, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Template for showing mobile network operator name while WFC is active -->
- <string-array name="wfcSpnFormats">
- <item>%s</item>
- <item>%s Wi-Fi</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-mcc302-mnc720/strings.xml b/core/res/res/values-mcc302-mnc720/strings.xml
deleted file mode 100644
index f5b8496..0000000
--- a/core/res/res/values-mcc302-mnc720/strings.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2017, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Template for showing mobile network operator name while WFC is active -->
- <string-array name="wfcSpnFormats">
- <item>%s</item>
- <item>%s Wi-Fi</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 632e439..477b17e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3463,4 +3463,12 @@
<!-- Whether or not swipe up gesture's opt-in setting is available on this device -->
<bool name="config_swipe_up_gesture_setting_available">false</bool>
+ <!-- Pre-scale volume at volume step 1 for Absolute Volume -->
+ <fraction name="config_prescaleAbsoluteVolume_index1">50%</fraction>
+
+ <!-- Pre-scale volume at volume step 2 for Absolute Volume -->
+ <fraction name="config_prescaleAbsoluteVolume_index2">70%</fraction>
+
+ <!-- Pre-scale volume at volume step 3 for Absolute Volume -->
+ <fraction name="config_prescaleAbsoluteVolume_index3">85%</fraction>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3c5159c..2549dd0 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -240,10 +240,31 @@
<item>Issue registering Wi\u2011Fi calling with your carrier: <xliff:g id="code" example="REG09 - No 911 Address">%1$s</xliff:g></item>
</string-array>
<!-- Template for showing mobile network operator name while WFC is active -->
- <string-array name="wfcSpnFormats">
- <item>%s</item>
- <item>%s Wi-Fi Calling</item>
+ <string-array name="wfcSpnFormats" translatable="false">
+ <item>@string/wfcSpnFormat_spn</item>
+ <item>@string/wfcSpnFormat_spn_wifi_calling</item>
+ <item>@string/wfcSpnFormat_wlan_call</item>
+ <item>@string/wfcSpnFormat_spn_wlan_call</item>
+ <item>@string/wfcSpnFormat_spn_wifi</item>
+ <item>@string/wfcSpnFormat_wifi_calling_bar_spn</item>
+ <item>@string/wfcSpnFormat_spn_vowifi</item>
</string-array>
+
+ <!-- Spn during Wi-Fi Calling: "<operator>" -->
+ <string name="wfcSpnFormat_spn"><xliff:g id="spn" example="Operator">%s</xliff:g></string>
+ <!-- Spn during Wi-Fi Calling: "<operator> Wi-Fi Calling" -->
+ <string name="wfcSpnFormat_spn_wifi_calling"><xliff:g id="spn" example="Operator">%s</xliff:g> Wi-Fi Calling</string>
+ <!-- Spn during Wi-Fi Calling: "WLAN Call" -->
+ <string name="wfcSpnFormat_wlan_call">WLAN Call</string>
+ <!-- Spn during Wi-Fi Calling: "<operator> WLAN Call" -->
+ <string name="wfcSpnFormat_spn_wlan_call"><xliff:g id="spn" example="Operator">%s</xliff:g> WLAN Call</string>
+ <!-- Spn during Wi-Fi Calling: "<operator> Wi-Fi" -->
+ <string name="wfcSpnFormat_spn_wifi"><xliff:g id="spn" example="Operator">%s</xliff:g> Wi-Fi</string>
+ <!-- Spn during Wi-Fi Calling: "WiFi Calling | <operator>" -->
+ <string name="wfcSpnFormat_wifi_calling_bar_spn">WiFi Calling | <xliff:g id="spn" example="Operator">%s</xliff:g></string>
+ <!-- Spn during Wi-Fi Calling: "<operator> VoWifi" -->
+ <string name="wfcSpnFormat_spn_vowifi"><xliff:g id="spn" example="Operator">%s</xliff:g> VoWifi</string>
+
<!-- WFC, summary for Disabled -->
<string name="wifi_calling_off_summary">Off</string>
<!-- WFC, summary for Wi-Fi Preferred -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index de5dc43..e9a54f1 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3393,4 +3393,9 @@
<java-symbol type="integer" name="config_defaultHapticFeedbackIntensity" />
<java-symbol type="integer" name="config_defaultNotificationVibrationIntensity" />
+
+ <!-- For Bluetooth AbsoluteVolume -->
+ <java-symbol type="fraction" name="config_prescaleAbsoluteVolume_index1" />
+ <java-symbol type="fraction" name="config_prescaleAbsoluteVolume_index2" />
+ <java-symbol type="fraction" name="config_prescaleAbsoluteVolume_index3" />
</resources>
diff --git a/core/tests/coretests/src/android/net/LocalSocketTest.java b/core/tests/coretests/src/android/net/LocalSocketTest.java
index 1349844..1286b13 100644
--- a/core/tests/coretests/src/android/net/LocalSocketTest.java
+++ b/core/tests/coretests/src/android/net/LocalSocketTest.java
@@ -22,6 +22,7 @@
import android.net.LocalSocketAddress;
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.SmallTest;
+
import junit.framework.TestCase;
import java.io.FileDescriptor;
@@ -39,6 +40,20 @@
ls = new LocalSocket();
+ try {
+ ls.connect(new LocalSocketAddress(null));
+ fail("Expected NullPointerException");
+ } catch (NullPointerException e) {
+ // pass
+ }
+
+ try {
+ ls.bind(new LocalSocketAddress(null));
+ fail("Expected NullPointerException");
+ } catch (NullPointerException e) {
+ // pass
+ }
+
ls.connect(new LocalSocketAddress("android.net.LocalSocketTest"));
ls1 = ss.accept();
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index cd96583..32790e5 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -456,6 +456,7 @@
Settings.Global.WFC_IMS_MODE,
Settings.Global.WFC_IMS_ROAMING_ENABLED,
Settings.Global.WFC_IMS_ROAMING_MODE,
+ Settings.Global.WIFI_ALWAYS_REQUESTED,
Settings.Global.WIFI_BADGING_THRESHOLDS,
Settings.Global.WIFI_BOUNCE_DELAY_OVERRIDE_MS,
Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED,
@@ -526,6 +527,7 @@
Settings.Secure.BACKUP_ENABLED,
Settings.Secure.BACKUP_PROVISIONED,
Settings.Secure.BACKUP_TRANSPORT,
+ Settings.Secure.CALL_REDIRECTION_DEFAULT_APPLICATION,
Settings.Secure.CAMERA_LIFT_TRIGGER_ENABLED, // Candidate for backup?
Settings.Secure.CARRIER_APPS_HANDLED,
Settings.Secure.CMAS_ADDITIONAL_BROADCAST_PKG,
diff --git a/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java b/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
index 45b19bc..a44b860 100644
--- a/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/DumpUtilsTest.java
@@ -15,8 +15,11 @@
*/
package com.android.internal.util;
+import static com.android.internal.util.DumpUtils.CRITICAL_SECTION_COMPONENTS;
import static com.android.internal.util.DumpUtils.filterRecord;
import static com.android.internal.util.DumpUtils.isNonPlatformPackage;
+import static com.android.internal.util.DumpUtils.isPlatformCriticalPackage;
+import static com.android.internal.util.DumpUtils.isPlatformNonCriticalPackage;
import static com.android.internal.util.DumpUtils.isPlatformPackage;
import android.content.ComponentName;
@@ -25,7 +28,7 @@
/**
* Run with:
- atest /android/pi-dev/frameworks/base/core/tests/coretests/src/com/android/internal/util/DumpTest.java
+ atest FrameworksCoreTests:DumpUtilsTest
*/
public class DumpUtilsTest extends TestCase {
@@ -89,6 +92,32 @@
assertTrue(isNonPlatformPackage(wcn("com.google.def/abc")));
}
+ public void testIsPlatformCriticalPackage() {
+ for (final ComponentName componentName : CRITICAL_SECTION_COMPONENTS) {
+ assertTrue(isPlatformCriticalPackage(() -> componentName));
+ assertTrue(isPlatformPackage(componentName));
+ }
+ assertFalse(isPlatformCriticalPackage(wcn("com.google.p/abc")));
+ assertFalse(isPlatformCriticalPackage(wcn("com.android.def/abc")));
+ assertFalse(isPlatformCriticalPackage(wcn("com.android.abc")));
+ assertFalse(isPlatformCriticalPackage(wcn("com.android")));
+ assertFalse(isPlatformCriticalPackage(wcn(null)));
+ assertFalse(isPlatformCriticalPackage(null));
+ }
+
+ public void testIsPlatformNonCriticalPackage() {
+ for (final ComponentName componentName : CRITICAL_SECTION_COMPONENTS) {
+ assertFalse(isPlatformNonCriticalPackage(() -> componentName));
+ }
+ assertTrue(isPlatformNonCriticalPackage(wcn("android/abc")));
+ assertTrue(isPlatformNonCriticalPackage(wcn("android.abc/abc")));
+ assertTrue(isPlatformNonCriticalPackage(wcn("com.android.def/abc")));
+
+ assertFalse(isPlatformNonCriticalPackage(wcn("com.google.def/abc")));
+ assertFalse(isPlatformNonCriticalPackage(wcn(null)));
+ assertFalse(isPlatformNonCriticalPackage(null));
+ }
+
public void testFilterRecord() {
assertFalse(filterRecord(null).test(wcn("com.google.p/abc")));
assertFalse(filterRecord(null).test(wcn("com.android.p/abc")));
@@ -105,6 +134,19 @@
assertFalse(filterRecord("all-non-platform").test(wcn("com.android.p/abc")));
assertFalse(filterRecord("all-non-platform").test(wcn(null)));
+ for (final ComponentName componentName : CRITICAL_SECTION_COMPONENTS) {
+ assertTrue(filterRecord("all-platform-critical").test((() -> componentName)));
+ assertFalse(filterRecord("all-platform-non-critical").test((() -> componentName)));
+ assertTrue(filterRecord("all-platform").test((() -> componentName)));
+ }
+ assertFalse(filterRecord("all-platform-critical").test(wcn("com.google.p/abc")));
+ assertFalse(filterRecord("all-platform-critical").test(wcn("com.android.p/abc")));
+ assertFalse(filterRecord("all-platform-critical").test(wcn(null)));
+
+ assertTrue(filterRecord("all-platform-non-critical").test(wcn("com.android.p/abc")));
+ assertFalse(filterRecord("all-platform-non-critical").test(wcn("com.google.p/abc")));
+ assertFalse(filterRecord("all-platform-non-critical").test(wcn(null)));
+
// Partial string match.
assertTrue(filterRecord("abc").test(wcn("com.google.p/.abc")));
assertFalse(filterRecord("abc").test(wcn("com.google.p/.def")));
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/Android.mk b/core/tests/overlaytests/device/test-apps/AppOverlayOne/Android.mk
index edad4b2..97a3d00 100644
--- a/core/tests/overlaytests/device/test-apps/AppOverlayOne/Android.mk
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/Android.mk
@@ -20,4 +20,6 @@
LOCAL_SDK_VERSION := current
LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_CERTIFICATE := platform
+LOCAL_USE_AAPT2 := true
+LOCAL_AAPT_FLAGS := --no-resource-removal
include $(BUILD_PACKAGE)
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayTwo/Android.mk b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/Android.mk
index 3fae8e1..a347025 100644
--- a/core/tests/overlaytests/device/test-apps/AppOverlayTwo/Android.mk
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayTwo/Android.mk
@@ -20,4 +20,6 @@
LOCAL_SDK_VERSION := current
LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_CERTIFICATE := platform
+LOCAL_USE_AAPT2 := true
+LOCAL_AAPT_FLAGS := --no-resource-removal
include $(BUILD_PACKAGE)
diff --git a/core/tests/overlaytests/device/test-apps/FrameworkOverlay/Android.mk b/core/tests/overlaytests/device/test-apps/FrameworkOverlay/Android.mk
index c352c05..e4819e1 100644
--- a/core/tests/overlaytests/device/test-apps/FrameworkOverlay/Android.mk
+++ b/core/tests/overlaytests/device/test-apps/FrameworkOverlay/Android.mk
@@ -20,4 +20,6 @@
LOCAL_SDK_VERSION := current
LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_CERTIFICATE := platform
+LOCAL_USE_AAPT2 := true
+LOCAL_AAPT_FLAGS := --no-resource-removal
include $(BUILD_PACKAGE)
diff --git a/core/tests/overlaytests/host/test-apps/UpdateOverlay/Android.mk b/core/tests/overlaytests/host/test-apps/UpdateOverlay/Android.mk
index ab3faf0..8656781 100644
--- a/core/tests/overlaytests/host/test-apps/UpdateOverlay/Android.mk
+++ b/core/tests/overlaytests/host/test-apps/UpdateOverlay/Android.mk
@@ -21,6 +21,8 @@
LOCAL_SDK_VERSION := current
LOCAL_COMPATIBILITY_SUITE := general-tests
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_USE_AAPT2 := true
+LOCAL_AAPT_FLAGS := --no-resource-removal
include $(BUILD_PACKAGE)
my_package_prefix := com.android.server.om.hosttest.framework_overlay
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index c4017d1..73c10d2 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -210,6 +210,11 @@
<allow-in-power-save-except-idle package="com.android.providers.calendar" />
<allow-in-power-save-except-idle package="com.android.providers.contacts" />
+ <!-- The PAC proxy process must have network access, otherwise no app will
+ be able to connect to the internet when such a proxy is in use, since
+ all outgoing connections originate from this app. -->
+ <allow-in-power-save-except-idle package="com.android.proxyhandler" />
+
<!-- These are the packages that are white-listed to be able to run as system user -->
<system-user-whitelisted-app package="com.android.settings" />
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 82b6a22..0082f4b 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -316,6 +316,7 @@
<permission name="android.permission.READ_FRAME_BUFFER"/>
<permission name="android.permission.READ_LOWPAN_CREDENTIAL"/>
<permission name="android.permission.REAL_GET_TASKS"/>
+ <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
<permission name="android.permission.REGISTER_CALL_PROVIDER"/>
<permission name="android.permission.REGISTER_CONNECTION_MANAGER"/>
<permission name="android.permission.REGISTER_SIM_SUBSCRIPTION"/>
diff --git a/data/keyboards/Vendor_054c_Product_0268.kl b/data/keyboards/Vendor_054c_Product_0268.kl
index 522db3c..b463dd8 100644
--- a/data/keyboards/Vendor_054c_Product_0268.kl
+++ b/data/keyboards/Vendor_054c_Product_0268.kl
@@ -21,8 +21,6 @@
key 0x126 DPAD_DOWN
key 0x127 DPAD_LEFT
-key 0x120 BUTTON_SELECT
-key 0x123 BUTTON_START
key 0x12e BUTTON_A
key 0x12d BUTTON_B
key 0x12f BUTTON_X
@@ -34,9 +32,6 @@
key 0x121 BUTTON_THUMBL
key 0x122 BUTTON_THUMBR
-# PS key
-key 0x2d0 BUTTON_MODE
-
# Left Analog Stick
axis 0x00 X
axis 0x01 Y
@@ -74,3 +69,11 @@
# Square
# axis 0x37
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Select
+key 0x120 BUTTON_SELECT
+# Start
+key 0x123 BUTTON_START
+# PS key
+key 0x2d0 BUTTON_MODE
diff --git a/data/keyboards/Vendor_054c_Product_0268_Version_8000.kl b/data/keyboards/Vendor_054c_Product_0268_Version_8000.kl
new file mode 100644
index 0000000..3d93f0f
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_0268_Version_8000.kl
@@ -0,0 +1,57 @@
+# Copyright (C) 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.
+
+#
+# Sony Playstation(R)3 Controller
+# - Version 0x8000 and 0x8100 are for Linux hid-sony driver >=4.12
+# and when connected over Bluetooth
+#
+
+key 0x220 DPAD_UP
+key 0x223 DPAD_RIGHT
+key 0x221 DPAD_DOWN
+key 0x222 DPAD_LEFT
+
+key 0x130 BUTTON_A
+key 0x131 BUTTON_B
+key 0x134 BUTTON_X
+key 0x133 BUTTON_Y
+key 0x136 BUTTON_L1
+key 0x137 BUTTON_R1
+key 0x138 BUTTON_L2
+key 0x139 BUTTON_R2
+key 0x13d BUTTON_THUMBL
+key 0x13e BUTTON_THUMBR
+
+# left Analog Stick
+axis 0x00 X
+axis 0x01 Y
+
+# Right Analog Stick
+axis 0x03 Z
+axis 0x04 RZ
+
+# L2 trigger
+axis 0x02 LTRIGGER
+
+# R2 trigger
+axis 0x05 RTRIGGER
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Select
+key 0x13a BUTTON_SELECT
+# Start
+key 0x13b BUTTON_START
+# PS key
+key 0x13c BUTTON_MODE
diff --git a/data/keyboards/Vendor_054c_Product_0268_Version_8100.kl b/data/keyboards/Vendor_054c_Product_0268_Version_8100.kl
new file mode 100644
index 0000000..3d93f0f
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_0268_Version_8100.kl
@@ -0,0 +1,57 @@
+# Copyright (C) 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.
+
+#
+# Sony Playstation(R)3 Controller
+# - Version 0x8000 and 0x8100 are for Linux hid-sony driver >=4.12
+# and when connected over Bluetooth
+#
+
+key 0x220 DPAD_UP
+key 0x223 DPAD_RIGHT
+key 0x221 DPAD_DOWN
+key 0x222 DPAD_LEFT
+
+key 0x130 BUTTON_A
+key 0x131 BUTTON_B
+key 0x134 BUTTON_X
+key 0x133 BUTTON_Y
+key 0x136 BUTTON_L1
+key 0x137 BUTTON_R1
+key 0x138 BUTTON_L2
+key 0x139 BUTTON_R2
+key 0x13d BUTTON_THUMBL
+key 0x13e BUTTON_THUMBR
+
+# left Analog Stick
+axis 0x00 X
+axis 0x01 Y
+
+# Right Analog Stick
+axis 0x03 Z
+axis 0x04 RZ
+
+# L2 trigger
+axis 0x02 LTRIGGER
+
+# R2 trigger
+axis 0x05 RTRIGGER
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Select
+key 0x13a BUTTON_SELECT
+# Start
+key 0x13b BUTTON_START
+# PS key
+key 0x13c BUTTON_MODE
diff --git a/data/keyboards/Vendor_054c_Product_0268_Version_8111.kl b/data/keyboards/Vendor_054c_Product_0268_Version_8111.kl
new file mode 100644
index 0000000..5fe35f7
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_0268_Version_8111.kl
@@ -0,0 +1,57 @@
+# Copyright (C) 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.
+
+#
+# Sony Playstation(R)3 Controller
+# - Version 0x8111 is for Linux hid-sony driver >=4.12 and when
+# connected over USB
+#
+
+key 0x220 DPAD_UP
+key 0x223 DPAD_RIGHT
+key 0x221 DPAD_DOWN
+key 0x222 DPAD_LEFT
+
+key 0x130 BUTTON_A
+key 0x131 BUTTON_B
+key 0x134 BUTTON_X
+key 0x133 BUTTON_Y
+key 0x136 BUTTON_L1
+key 0x137 BUTTON_R1
+key 0x138 BUTTON_L2
+key 0x139 BUTTON_R2
+key 0x13d BUTTON_THUMBL
+key 0x13e BUTTON_THUMBR
+
+# left Analog Stick
+axis 0x00 X
+axis 0x01 Y
+
+# Right Analog Stick
+axis 0x03 Z
+axis 0x04 RZ
+
+# L2 trigger
+axis 0x02 LTRIGGER
+
+# R2 trigger
+axis 0x05 RTRIGGER
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Select
+key 0x13a BUTTON_SELECT
+# Start
+key 0x13b BUTTON_START
+# PS key
+key 0x13c BUTTON_MODE
diff --git a/data/keyboards/Vendor_054c_Product_05c4.kl b/data/keyboards/Vendor_054c_Product_05c4.kl
index a1284a4..cd7ab1f 100644
--- a/data/keyboards/Vendor_054c_Product_05c4.kl
+++ b/data/keyboards/Vendor_054c_Product_05c4.kl
@@ -60,7 +60,6 @@
key 0x138 BUTTON_SELECT
# Options
key 0x139 BUTTON_START
-
# PS key
key 0x13c BUTTON_MODE
diff --git a/data/keyboards/Vendor_054c_Product_05c4_Version_8000.kl b/data/keyboards/Vendor_054c_Product_05c4_Version_8000.kl
new file mode 100644
index 0000000..19fcb86
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_05c4_Version_8000.kl
@@ -0,0 +1,68 @@
+# Copyright (C) 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.
+
+#
+# Sony Playstation(R) DualShock 4 Controller
+# - Version 0x8000 and 0x8100 are for Linux hid-sony driver >=4.10
+# and when connected over Bluetooth
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 0x134 BUTTON_X
+# Cross
+key 0x130 BUTTON_A
+# Circle
+key 0x131 BUTTON_B
+# Triangle
+key 0x133 BUTTON_Y
+
+key 0x136 BUTTON_L1
+key 0x137 BUTTON_R1
+key 0x138 BUTTON_L2
+key 0x139 BUTTON_R2
+
+# L2 axis
+axis 0x02 LTRIGGER
+# R2 axis
+axis 0x05 RTRIGGER
+
+# Left Analog Stick
+axis 0x00 X
+axis 0x01 Y
+# Right Analog Stick
+axis 0x03 Z
+axis 0x04 RZ
+
+# Left stick click
+key 0x13d BUTTON_THUMBL
+# Right stick click
+key 0x13e BUTTON_THUMBR
+
+# Hat
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share
+key 0x13a BUTTON_SELECT
+# Options
+key 0x13b BUTTON_START
+# PS key
+key 0x13c BUTTON_MODE
+
+# In kernel versions >= 4.10, the touchpad is a separate input device,
+# so the touchpad button click will not be covered by this layout.
diff --git a/data/keyboards/Vendor_054c_Product_05c4_Version_8100.kl b/data/keyboards/Vendor_054c_Product_05c4_Version_8100.kl
new file mode 100644
index 0000000..19fcb86
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_05c4_Version_8100.kl
@@ -0,0 +1,68 @@
+# Copyright (C) 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.
+
+#
+# Sony Playstation(R) DualShock 4 Controller
+# - Version 0x8000 and 0x8100 are for Linux hid-sony driver >=4.10
+# and when connected over Bluetooth
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 0x134 BUTTON_X
+# Cross
+key 0x130 BUTTON_A
+# Circle
+key 0x131 BUTTON_B
+# Triangle
+key 0x133 BUTTON_Y
+
+key 0x136 BUTTON_L1
+key 0x137 BUTTON_R1
+key 0x138 BUTTON_L2
+key 0x139 BUTTON_R2
+
+# L2 axis
+axis 0x02 LTRIGGER
+# R2 axis
+axis 0x05 RTRIGGER
+
+# Left Analog Stick
+axis 0x00 X
+axis 0x01 Y
+# Right Analog Stick
+axis 0x03 Z
+axis 0x04 RZ
+
+# Left stick click
+key 0x13d BUTTON_THUMBL
+# Right stick click
+key 0x13e BUTTON_THUMBR
+
+# Hat
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share
+key 0x13a BUTTON_SELECT
+# Options
+key 0x13b BUTTON_START
+# PS key
+key 0x13c BUTTON_MODE
+
+# In kernel versions >= 4.10, the touchpad is a separate input device,
+# so the touchpad button click will not be covered by this layout.
diff --git a/data/keyboards/Vendor_054c_Product_05c4_Version_8111.kl b/data/keyboards/Vendor_054c_Product_05c4_Version_8111.kl
new file mode 100644
index 0000000..d38bdec
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_05c4_Version_8111.kl
@@ -0,0 +1,68 @@
+# Copyright (C) 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.
+
+#
+# Sony Playstation(R) DualShock 4 Controller
+# - Version 0x8111 is for Linux hid-sony driver >=4.10 and when
+# connected over USB
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 0x134 BUTTON_X
+# Cross
+key 0x130 BUTTON_A
+# Circle
+key 0x131 BUTTON_B
+# Triangle
+key 0x133 BUTTON_Y
+
+key 0x136 BUTTON_L1
+key 0x137 BUTTON_R1
+key 0x138 BUTTON_L2
+key 0x139 BUTTON_R2
+
+# L2 axis
+axis 0x02 LTRIGGER
+# R2 axis
+axis 0x05 RTRIGGER
+
+# Left Analog Stick
+axis 0x00 X
+axis 0x01 Y
+# Right Analog Stick
+axis 0x03 Z
+axis 0x04 RZ
+
+# Left stick click
+key 0x13d BUTTON_THUMBL
+# Right stick click
+key 0x13e BUTTON_THUMBR
+
+# Hat
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share
+key 0x13a BUTTON_SELECT
+# Options
+key 0x13b BUTTON_START
+# PS key
+key 0x13c BUTTON_MODE
+
+# In kernel versions >= 4.10, the touchpad is a separate input device,
+# so the touchpad button click will not be covered by this layout.
diff --git a/data/keyboards/Vendor_054c_Product_09cc.kl b/data/keyboards/Vendor_054c_Product_09cc.kl
index a1284a4..cd7ab1f 100644
--- a/data/keyboards/Vendor_054c_Product_09cc.kl
+++ b/data/keyboards/Vendor_054c_Product_09cc.kl
@@ -60,7 +60,6 @@
key 0x138 BUTTON_SELECT
# Options
key 0x139 BUTTON_START
-
# PS key
key 0x13c BUTTON_MODE
diff --git a/data/keyboards/Vendor_054c_Product_09cc_Version_8000.kl b/data/keyboards/Vendor_054c_Product_09cc_Version_8000.kl
new file mode 100644
index 0000000..19fcb86
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_09cc_Version_8000.kl
@@ -0,0 +1,68 @@
+# Copyright (C) 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.
+
+#
+# Sony Playstation(R) DualShock 4 Controller
+# - Version 0x8000 and 0x8100 are for Linux hid-sony driver >=4.10
+# and when connected over Bluetooth
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 0x134 BUTTON_X
+# Cross
+key 0x130 BUTTON_A
+# Circle
+key 0x131 BUTTON_B
+# Triangle
+key 0x133 BUTTON_Y
+
+key 0x136 BUTTON_L1
+key 0x137 BUTTON_R1
+key 0x138 BUTTON_L2
+key 0x139 BUTTON_R2
+
+# L2 axis
+axis 0x02 LTRIGGER
+# R2 axis
+axis 0x05 RTRIGGER
+
+# Left Analog Stick
+axis 0x00 X
+axis 0x01 Y
+# Right Analog Stick
+axis 0x03 Z
+axis 0x04 RZ
+
+# Left stick click
+key 0x13d BUTTON_THUMBL
+# Right stick click
+key 0x13e BUTTON_THUMBR
+
+# Hat
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share
+key 0x13a BUTTON_SELECT
+# Options
+key 0x13b BUTTON_START
+# PS key
+key 0x13c BUTTON_MODE
+
+# In kernel versions >= 4.10, the touchpad is a separate input device,
+# so the touchpad button click will not be covered by this layout.
diff --git a/data/keyboards/Vendor_054c_Product_09cc_Version_8100.kl b/data/keyboards/Vendor_054c_Product_09cc_Version_8100.kl
new file mode 100644
index 0000000..19fcb86
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_09cc_Version_8100.kl
@@ -0,0 +1,68 @@
+# Copyright (C) 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.
+
+#
+# Sony Playstation(R) DualShock 4 Controller
+# - Version 0x8000 and 0x8100 are for Linux hid-sony driver >=4.10
+# and when connected over Bluetooth
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 0x134 BUTTON_X
+# Cross
+key 0x130 BUTTON_A
+# Circle
+key 0x131 BUTTON_B
+# Triangle
+key 0x133 BUTTON_Y
+
+key 0x136 BUTTON_L1
+key 0x137 BUTTON_R1
+key 0x138 BUTTON_L2
+key 0x139 BUTTON_R2
+
+# L2 axis
+axis 0x02 LTRIGGER
+# R2 axis
+axis 0x05 RTRIGGER
+
+# Left Analog Stick
+axis 0x00 X
+axis 0x01 Y
+# Right Analog Stick
+axis 0x03 Z
+axis 0x04 RZ
+
+# Left stick click
+key 0x13d BUTTON_THUMBL
+# Right stick click
+key 0x13e BUTTON_THUMBR
+
+# Hat
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share
+key 0x13a BUTTON_SELECT
+# Options
+key 0x13b BUTTON_START
+# PS key
+key 0x13c BUTTON_MODE
+
+# In kernel versions >= 4.10, the touchpad is a separate input device,
+# so the touchpad button click will not be covered by this layout.
diff --git a/data/keyboards/Vendor_054c_Product_09cc_Version_8111.kl b/data/keyboards/Vendor_054c_Product_09cc_Version_8111.kl
new file mode 100644
index 0000000..d38bdec
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_09cc_Version_8111.kl
@@ -0,0 +1,68 @@
+# Copyright (C) 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.
+
+#
+# Sony Playstation(R) DualShock 4 Controller
+# - Version 0x8111 is for Linux hid-sony driver >=4.10 and when
+# connected over USB
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 0x134 BUTTON_X
+# Cross
+key 0x130 BUTTON_A
+# Circle
+key 0x131 BUTTON_B
+# Triangle
+key 0x133 BUTTON_Y
+
+key 0x136 BUTTON_L1
+key 0x137 BUTTON_R1
+key 0x138 BUTTON_L2
+key 0x139 BUTTON_R2
+
+# L2 axis
+axis 0x02 LTRIGGER
+# R2 axis
+axis 0x05 RTRIGGER
+
+# Left Analog Stick
+axis 0x00 X
+axis 0x01 Y
+# Right Analog Stick
+axis 0x03 Z
+axis 0x04 RZ
+
+# Left stick click
+key 0x13d BUTTON_THUMBL
+# Right stick click
+key 0x13e BUTTON_THUMBR
+
+# Hat
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share
+key 0x13a BUTTON_SELECT
+# Options
+key 0x13b BUTTON_START
+# PS key
+key 0x13c BUTTON_MODE
+
+# In kernel versions >= 4.10, the touchpad is a separate input device,
+# so the touchpad button click will not be covered by this layout.
diff --git a/data/keyboards/Vendor_054c_Product_0ba0.kl b/data/keyboards/Vendor_054c_Product_0ba0.kl
new file mode 100644
index 0000000..bc6fc3b
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_0ba0.kl
@@ -0,0 +1,70 @@
+# Copyright (C) 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.
+
+#
+# Sony Playstation(R) DualShock 4 USB Dongle
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 0x130 BUTTON_X
+# Cross
+key 0x131 BUTTON_A
+# Circle
+key 0x132 BUTTON_B
+# Triangle
+key 0x133 BUTTON_Y
+
+key 0x134 BUTTON_L1
+key 0x135 BUTTON_R1
+key 0x136 BUTTON_L2
+key 0x137 BUTTON_R2
+
+# L2 axis
+axis 0x03 LTRIGGER
+# R2 axis
+axis 0x04 RTRIGGER
+
+
+# Left Analog Stick
+axis 0x00 X
+axis 0x01 Y
+# Right Analog Stick
+axis 0x02 Z
+axis 0x05 RZ
+
+# Left stick click
+key 0x13a BUTTON_THUMBL
+# Right stick click
+key 0x13b BUTTON_THUMBR
+
+# Hat
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share
+key 0x138 BUTTON_SELECT
+# Options
+key 0x139 BUTTON_START
+# PS key
+key 0x13c BUTTON_MODE
+
+# Touchpad press
+# The touchpad for this joystick will become a separate input device in future releases
+# and this button will be equivalent to left mouse button
+# Therefore, map it to KEYCODE_BUTTON_1 here to allow apps to still handle this on earlier versions
+key 0x13d BUTTON_1
diff --git a/data/keyboards/Vendor_054c_Product_0ba0_Version_8111.kl b/data/keyboards/Vendor_054c_Product_0ba0_Version_8111.kl
new file mode 100644
index 0000000..8b85a38
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_0ba0_Version_8111.kl
@@ -0,0 +1,67 @@
+# Copyright (C) 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.
+
+#
+# Sony Playstation(R) DualShock 4 USB Dongle
+# - Version 0x8111 is for Linux hid-sony driver >=4.10
+#
+
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Square
+key 0x134 BUTTON_X
+# Cross
+key 0x130 BUTTON_A
+# Circle
+key 0x131 BUTTON_B
+# Triangle
+key 0x133 BUTTON_Y
+
+key 0x136 BUTTON_L1
+key 0x137 BUTTON_R1
+key 0x138 BUTTON_L2
+key 0x139 BUTTON_R2
+
+# L2 axis
+axis 0x02 LTRIGGER
+# R2 axis
+axis 0x05 RTRIGGER
+
+# Left Analog Stick
+axis 0x00 X
+axis 0x01 Y
+# Right Analog Stick
+axis 0x03 Z
+axis 0x04 RZ
+
+# Left stick click
+key 0x13d BUTTON_THUMBL
+# Right stick click
+key 0x13e BUTTON_THUMBR
+
+# Hat
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Mapping according to https://www.kernel.org/doc/Documentation/input/gamepad.txt
+# Share
+key 0x13a BUTTON_SELECT
+# Options
+key 0x13b BUTTON_START
+# PS key
+key 0x13c BUTTON_MODE
+
+# In kernel versions >= 4.10, the touchpad is a separate input device,
+# so the touchpad button click will not be covered by this layout.
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index e39926b..140001d 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -43,11 +43,14 @@
"AssetManager2.cpp",
"AttributeResolution.cpp",
"ChunkIterator.cpp",
+ "ConfigDescription.cpp",
"Idmap.cpp",
"LoadedArsc.cpp",
+ "Locale.cpp",
"LocaleData.cpp",
"misc.cpp",
"ObbFile.cpp",
+ "PosixUtils.cpp",
"ResourceTypes.cpp",
"ResourceUtils.cpp",
"StreamingZipInflater.cpp",
@@ -135,9 +138,11 @@
"tests/AttributeResolution_test.cpp",
"tests/ByteBucketArray_test.cpp",
"tests/Config_test.cpp",
+ "tests/ConfigDescription_test.cpp",
"tests/ConfigLocale_test.cpp",
"tests/Idmap_test.cpp",
"tests/LoadedArsc_test.cpp",
+ "tests/Locale_test.cpp",
"tests/ResourceUtils_test.cpp",
"tests/ResTable_test.cpp",
"tests/Split_test.cpp",
@@ -152,6 +157,7 @@
srcs: [
"tests/BackupData_test.cpp",
"tests/ObbFile_test.cpp",
+ "tests/PosixUtils_test.cpp",
],
shared_libs: common_test_libs + ["libui"],
},
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 9c1629b..04cc5bb 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -67,10 +67,10 @@
}
bool AssetManager2::SetApkAssets(const std::vector<const ApkAssets*>& apk_assets,
- bool invalidate_caches) {
+ bool invalidate_caches, bool filter_incompatible_configs) {
apk_assets_ = apk_assets;
BuildDynamicRefTable();
- RebuildFilterList();
+ RebuildFilterList(filter_incompatible_configs);
if (invalidate_caches) {
InvalidateCaches(static_cast<uint32_t>(-1));
}
@@ -825,7 +825,7 @@
return 0u;
}
-void AssetManager2::RebuildFilterList() {
+void AssetManager2::RebuildFilterList(bool filter_incompatible_configs) {
for (PackageGroup& group : package_groups_) {
for (ConfiguredPackage& impl : group.packages_) {
// Destroy it.
@@ -841,7 +841,7 @@
for (auto iter = spec->types; iter != iter_end; ++iter) {
ResTable_config this_config;
this_config.copyFromDtoH((*iter)->config);
- if (this_config.match(configuration_)) {
+ if (!filter_incompatible_configs || this_config.match(configuration_)) {
group.configurations.push_back(this_config);
group.types.push_back(*iter);
}
diff --git a/tools/aapt2/ConfigDescription.cpp b/libs/androidfw/ConfigDescription.cpp
similarity index 98%
rename from tools/aapt2/ConfigDescription.cpp
rename to libs/androidfw/ConfigDescription.cpp
index f621660..1f3a89e 100644
--- a/tools/aapt2/ConfigDescription.cpp
+++ b/libs/androidfw/ConfigDescription.cpp
@@ -14,22 +14,16 @@
* limitations under the License.
*/
-#include "ConfigDescription.h"
+#include "androidfw/ConfigDescription.h"
+#include "androidfw/Locale.h"
+#include "androidfw/ResourceTypes.h"
+#include "androidfw/StringPiece.h"
+#include "androidfw/Util.h"
#include <string>
#include <vector>
-#include "androidfw/ResourceTypes.h"
-#include "androidfw/StringPiece.h"
-
-#include "Locale.h"
-#include "SdkConstants.h"
-#include "util/Util.h"
-
-using android::ResTable_config;
-using android::StringPiece;
-
-namespace aapt {
+namespace android {
static const char* kWildcardName = "any";
@@ -883,7 +877,7 @@
}
std::string ConfigDescription::to_string() const {
- const android::String8 str = toString();
+ const String8 str = toString();
return std::string(str.string(), str.size());
}
@@ -996,4 +990,4 @@
return !ConflictsWith(o) && !Dominates(o) && !o.Dominates(*this);
}
-} // namespace aapt
+} // namespace android
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index 04d506a..21f023d 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -203,6 +203,39 @@
return true;
}
+LoadedPackage::iterator::iterator(const LoadedPackage* lp, size_t ti, size_t ei)
+ : loadedPackage_(lp),
+ typeIndex_(ti),
+ entryIndex_(ei),
+ typeIndexEnd_(lp->resource_ids_.size() + 1) {
+ while (typeIndex_ < typeIndexEnd_ && loadedPackage_->resource_ids_[typeIndex_] == 0) {
+ typeIndex_++;
+ }
+}
+
+LoadedPackage::iterator& LoadedPackage::iterator::operator++() {
+ while (typeIndex_ < typeIndexEnd_) {
+ if (entryIndex_ + 1 < loadedPackage_->resource_ids_[typeIndex_]) {
+ entryIndex_++;
+ break;
+ }
+ entryIndex_ = 0;
+ typeIndex_++;
+ if (typeIndex_ < typeIndexEnd_ && loadedPackage_->resource_ids_[typeIndex_] != 0) {
+ break;
+ }
+ }
+ return *this;
+}
+
+uint32_t LoadedPackage::iterator::operator*() const {
+ if (typeIndex_ >= typeIndexEnd_) {
+ return 0;
+ }
+ return make_resid(loadedPackage_->package_id_, typeIndex_ + loadedPackage_->type_id_offset_,
+ entryIndex_);
+}
+
const ResTable_entry* LoadedPackage::GetEntry(const ResTable_type* type_chunk,
uint16_t entry_index) {
uint32_t entry_offset = GetEntryOffset(type_chunk, entry_index);
@@ -488,6 +521,7 @@
std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type_spec->id - 1];
if (builder_ptr == nullptr) {
builder_ptr = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header);
+ loaded_package->resource_ids_.set(type_spec->id, entry_count);
} else {
LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x",
type_spec->id);
diff --git a/tools/aapt2/Locale.cpp b/libs/androidfw/Locale.cpp
similarity index 98%
rename from tools/aapt2/Locale.cpp
rename to libs/androidfw/Locale.cpp
index d81921f..2870066 100644
--- a/tools/aapt2/Locale.cpp
+++ b/libs/androidfw/Locale.cpp
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#include "Locale.h"
+#include "androidfw/Locale.h"
+#include "androidfw/Util.h"
#include <ctype.h>
@@ -22,12 +23,10 @@
#include <string>
#include <vector>
-#include "util/Util.h"
-
using ::android::ResTable_config;
using ::android::StringPiece;
-namespace aapt {
+namespace android {
void LocaleValue::set_language(const char* language_chars) {
size_t i = 0;
@@ -258,4 +257,4 @@
}
}
-} // namespace aapt
+} // namespace android
diff --git a/libs/androidfw/PosixUtils.cpp b/libs/androidfw/PosixUtils.cpp
new file mode 100644
index 0000000..df0dd7c
--- /dev/null
+++ b/libs/androidfw/PosixUtils.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifdef _WIN32
+// nothing to see here
+#else
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "android-base/logging.h"
+
+#include "androidfw/PosixUtils.h"
+
+namespace {
+
+std::unique_ptr<std::string> ReadFile(int fd) {
+ std::unique_ptr<std::string> str(new std::string());
+ char buf[1024];
+ ssize_t r;
+ while ((r = read(fd, buf, sizeof(buf))) > 0) {
+ str->append(buf, r);
+ }
+ if (r != 0) {
+ return nullptr;
+ }
+ return str;
+}
+
+}
+
+namespace android {
+namespace util {
+
+std::unique_ptr<ProcResult> ExecuteBinary(const std::vector<std::string>& argv) {
+ int stdout[2]; // stdout[0] read, stdout[1] write
+ if (pipe(stdout) != 0) {
+ PLOG(ERROR) << "pipe";
+ return nullptr;
+ }
+
+ int stderr[2]; // stdout[0] read, stdout[1] write
+ if (pipe(stderr) != 0) {
+ PLOG(ERROR) << "pipe";
+ close(stdout[0]);
+ close(stdout[1]);
+ return nullptr;
+ }
+
+ char const** argv0 = (char const**)malloc(sizeof(char*) * (argv.size() + 1));
+ for (size_t i = 0; i < argv.size(); i++) {
+ argv0[i] = argv[i].c_str();
+ }
+ argv0[argv.size()] = nullptr;
+ switch (fork()) {
+ case -1: // error
+ free(argv0);
+ PLOG(ERROR) << "fork";
+ return nullptr;
+ case 0: // child
+ close(stdout[0]);
+ if (dup2(stdout[1], STDOUT_FILENO) == -1) {
+ abort();
+ }
+ close(stderr[0]);
+ if (dup2(stderr[1], STDERR_FILENO) == -1) {
+ abort();
+ }
+ execvp(argv0[0], const_cast<char* const*>(argv0));
+ PLOG(ERROR) << "execv";
+ abort();
+ default: // parent
+ free(argv0);
+ close(stdout[1]);
+ close(stderr[1]);
+ int status;
+ wait(&status);
+ if (!WIFEXITED(status)) {
+ return nullptr;
+ }
+ std::unique_ptr<ProcResult> result(new ProcResult());
+ result->status = status;
+ const auto out = ReadFile(stdout[0]);
+ result->stdout = out ? *out : "";
+ close(stdout[0]);
+ const auto err = ReadFile(stderr[0]);
+ result->stderr = err ? *err : "";
+ close(stderr[0]);
+ return result;
+ }
+}
+
+} // namespace util
+} // namespace android
+#endif
diff --git a/libs/androidfw/Util.cpp b/libs/androidfw/Util.cpp
index 575cd18..59c9d64 100644
--- a/libs/androidfw/Util.cpp
+++ b/libs/androidfw/Util.cpp
@@ -16,6 +16,7 @@
#include "androidfw/Util.h"
+#include <algorithm>
#include <string>
#include "utils/ByteOrder.h"
@@ -67,5 +68,28 @@
return utf8;
}
+static std::vector<std::string> SplitAndTransform(
+ const StringPiece& str, char sep, const std::function<char(char)>& f) {
+ std::vector<std::string> parts;
+ const StringPiece::const_iterator end = std::end(str);
+ StringPiece::const_iterator start = std::begin(str);
+ StringPiece::const_iterator current;
+ do {
+ current = std::find(start, end, sep);
+ parts.emplace_back(str.substr(start, current).to_string());
+ if (f) {
+ std::string& part = parts.back();
+ std::transform(part.begin(), part.end(), part.begin(), f);
+ }
+ start = current + 1;
+ } while (current != end);
+ return parts;
+}
+
+std::vector<std::string> SplitAndLowercase(const StringPiece& str, char sep) {
+ return SplitAndTransform(str, sep, ::tolower);
+}
+
+
} // namespace util
} // namespace android
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index ad31f69..2f0ee01 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -96,7 +96,12 @@
// Only pass invalidate_caches=false when it is known that the structure
// change in ApkAssets is due to a safe addition of resources with completely
// new resource IDs.
- bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true);
+ //
+ // Only pass in filter_incompatible_configs=false when you want to load all
+ // configurations (including incompatible ones) such as when constructing an
+ // idmap.
+ bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true,
+ bool filter_incompatible_configs = true);
inline const std::vector<const ApkAssets*> GetApkAssets() const {
return apk_assets_;
@@ -274,7 +279,7 @@
// Triggers the re-construction of lists of types that match the set configuration.
// This should always be called when mutating the AssetManager's configuration or ApkAssets set.
- void RebuildFilterList();
+ void RebuildFilterList(bool filter_incompatible_configs = true);
// AssetManager2::GetBag(resid) wraps this function to track which resource ids have already
// been seen while traversing bag parents.
diff --git a/tools/aapt2/ConfigDescription.h b/libs/androidfw/include/androidfw/ConfigDescription.h
similarity index 84%
rename from tools/aapt2/ConfigDescription.h
rename to libs/androidfw/include/androidfw/ConfigDescription.h
index f719552..29424c4 100644
--- a/tools/aapt2/ConfigDescription.h
+++ b/libs/androidfw/include/androidfw/ConfigDescription.h
@@ -14,21 +14,52 @@
* limitations under the License.
*/
-#ifndef AAPT_CONFIG_DESCRIPTION_H
-#define AAPT_CONFIG_DESCRIPTION_H
+#ifndef ANDROIDFW_CONFIG_DESCRIPTION_H
+#define ANDROIDFW_CONFIG_DESCRIPTION_H
#include <ostream>
#include "androidfw/ResourceTypes.h"
#include "androidfw/StringPiece.h"
-namespace aapt {
+namespace android {
+
+using ApiVersion = int;
+
+enum : ApiVersion {
+ SDK_CUPCAKE = 3,
+ SDK_DONUT = 4,
+ SDK_ECLAIR = 5,
+ SDK_ECLAIR_0_1 = 6,
+ SDK_ECLAIR_MR1 = 7,
+ SDK_FROYO = 8,
+ SDK_GINGERBREAD = 9,
+ SDK_GINGERBREAD_MR1 = 10,
+ SDK_HONEYCOMB = 11,
+ SDK_HONEYCOMB_MR1 = 12,
+ SDK_HONEYCOMB_MR2 = 13,
+ SDK_ICE_CREAM_SANDWICH = 14,
+ SDK_ICE_CREAM_SANDWICH_MR1 = 15,
+ SDK_JELLY_BEAN = 16,
+ SDK_JELLY_BEAN_MR1 = 17,
+ SDK_JELLY_BEAN_MR2 = 18,
+ SDK_KITKAT = 19,
+ SDK_KITKAT_WATCH = 20,
+ SDK_LOLLIPOP = 21,
+ SDK_LOLLIPOP_MR1 = 22,
+ SDK_MARSHMALLOW = 23,
+ SDK_NOUGAT = 24,
+ SDK_NOUGAT_MR1 = 25,
+ SDK_O = 26,
+ SDK_O_MR1 = 27,
+ SDK_P = 28,
+};
/*
* Subclass of ResTable_config that adds convenient
* initialization and comparison methods.
*/
-struct ConfigDescription : public android::ResTable_config {
+struct ConfigDescription : public ResTable_config {
/**
* Returns an immutable default config.
*/
@@ -53,11 +84,11 @@
ConfigDescription();
ConfigDescription(const android::ResTable_config& o); // NOLINT(implicit)
ConfigDescription(const ConfigDescription& o);
- ConfigDescription(ConfigDescription&& o);
+ ConfigDescription(ConfigDescription&& o) noexcept;
ConfigDescription& operator=(const android::ResTable_config& o);
ConfigDescription& operator=(const ConfigDescription& o);
- ConfigDescription& operator=(ConfigDescription&& o);
+ ConfigDescription& operator=(ConfigDescription&& o) noexcept;
ConfigDescription CopyWithoutSdkVersion() const;
@@ -124,7 +155,7 @@
*static_cast<android::ResTable_config*>(this) = o;
}
-inline ConfigDescription::ConfigDescription(ConfigDescription&& o) {
+inline ConfigDescription::ConfigDescription(ConfigDescription&& o) noexcept {
*this = o;
}
@@ -141,7 +172,7 @@
return *this;
}
-inline ConfigDescription& ConfigDescription::operator=(ConfigDescription&& o) {
+inline ConfigDescription& ConfigDescription::operator=(ConfigDescription&& o) noexcept {
*this = o;
return *this;
}
@@ -180,6 +211,6 @@
return out << o.toString().string();
}
-} // namespace aapt
+} // namespace android
-#endif // AAPT_CONFIG_DESCRIPTION_H
+#endif // ANDROIDFW_CONFIG_DESCRIPTION_H
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 35ae5fc..349b379 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -78,6 +78,55 @@
class LoadedPackage {
public:
+ class iterator {
+ public:
+ iterator& operator=(const iterator& rhs) {
+ loadedPackage_ = rhs.loadedPackage_;
+ typeIndex_ = rhs.typeIndex_;
+ entryIndex_ = rhs.entryIndex_;
+ return *this;
+ }
+
+ bool operator==(const iterator& rhs) const {
+ return loadedPackage_ == rhs.loadedPackage_ &&
+ typeIndex_ == rhs.typeIndex_ &&
+ entryIndex_ == rhs.entryIndex_;
+ }
+
+ bool operator!=(const iterator& rhs) const {
+ return !(*this == rhs);
+ }
+
+ iterator operator++(int) {
+ size_t prevTypeIndex_ = typeIndex_;
+ size_t prevEntryIndex_ = entryIndex_;
+ operator++();
+ return iterator(loadedPackage_, prevTypeIndex_, prevEntryIndex_);
+ }
+
+ iterator& operator++();
+
+ uint32_t operator*() const;
+
+ private:
+ friend class LoadedPackage;
+
+ iterator(const LoadedPackage* lp, size_t ti, size_t ei);
+
+ const LoadedPackage* loadedPackage_;
+ size_t typeIndex_;
+ size_t entryIndex_;
+ const size_t typeIndexEnd_; // STL style end, so one past the last element
+ };
+
+ iterator begin() const {
+ return iterator(this, 0, 0);
+ }
+
+ iterator end() const {
+ return iterator(this, resource_ids_.size() + 1, 0);
+ }
+
static std::unique_ptr<const LoadedPackage> Load(const Chunk& chunk,
const LoadedIdmap* loaded_idmap, bool system,
bool load_as_shared_library);
@@ -182,6 +231,7 @@
bool overlay_ = false;
ByteBucketArray<TypeSpecPtr> type_specs_;
+ ByteBucketArray<uint32_t> resource_ids_;
std::vector<DynamicPackageEntry> dynamic_package_map_;
};
diff --git a/tools/aapt2/Locale.h b/libs/androidfw/include/androidfw/Locale.h
similarity index 94%
rename from tools/aapt2/Locale.h
rename to libs/androidfw/include/androidfw/Locale.h
index 6d8b598..484ed79 100644
--- a/tools/aapt2/Locale.h
+++ b/libs/androidfw/include/androidfw/Locale.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef AAPT_LOCALE_VALUE_H
-#define AAPT_LOCALE_VALUE_H
+#ifndef ANDROIDFW_LOCALE_VALUE_H
+#define ANDROIDFW_LOCALE_VALUE_H
#include <string>
#include <vector>
@@ -23,7 +23,7 @@
#include "androidfw/ResourceTypes.h"
#include "androidfw/StringPiece.h"
-namespace aapt {
+namespace android {
/**
* A convenience class to build and parse locales.
@@ -112,6 +112,6 @@
return compare(o) > 0;
}
-} // namespace aapt
+} // namespace android
-#endif // AAPT_LOCALE_VALUE_H
+#endif // ANDROIDFW_LOCALE_VALUE_H
diff --git a/libs/androidfw/include/androidfw/PosixUtils.h b/libs/androidfw/include/androidfw/PosixUtils.h
new file mode 100644
index 0000000..8fc3ee2
--- /dev/null
+++ b/libs/androidfw/include/androidfw/PosixUtils.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace android {
+namespace util {
+
+struct ProcResult {
+ int status;
+ std::string stdout;
+ std::string stderr;
+};
+
+// Fork, exec and wait for an external process. Return nullptr if the process could not be launched,
+// otherwise a ProcResult containing the external process' exit status and captured stdout and
+// stderr.
+std::unique_ptr<ProcResult> ExecuteBinary(const std::vector<std::string>& argv);
+
+} // namespace util
+} // namespace android
diff --git a/libs/androidfw/include/androidfw/Util.h b/libs/androidfw/include/androidfw/Util.h
index e4cd6a8..10d088e 100644
--- a/libs/androidfw/include/androidfw/Util.h
+++ b/libs/androidfw/include/androidfw/Util.h
@@ -19,6 +19,7 @@
#include <cstdlib>
#include <memory>
+#include <vector>
#include "android-base/macros.h"
@@ -47,11 +48,11 @@
constexpr unique_cptr() : ptr_(nullptr) {}
constexpr unique_cptr(std::nullptr_t) : ptr_(nullptr) {}
explicit unique_cptr(pointer ptr) : ptr_(ptr) {}
- unique_cptr(unique_cptr&& o) : ptr_(o.ptr_) { o.ptr_ = nullptr; }
+ unique_cptr(unique_cptr&& o) noexcept : ptr_(o.ptr_) { o.ptr_ = nullptr; }
~unique_cptr() { std::free(reinterpret_cast<void*>(ptr_)); }
- inline unique_cptr& operator=(unique_cptr&& o) {
+ inline unique_cptr& operator=(unique_cptr&& o) noexcept {
if (&o == this) {
return *this;
}
@@ -116,6 +117,8 @@
// Converts a UTF-16 string to a UTF-8 string.
std::string Utf16ToUtf8(const StringPiece16& utf16);
+std::vector<std::string> SplitAndLowercase(const android::StringPiece& str, char sep);
+
} // namespace util
} // namespace android
diff --git a/tools/aapt2/ConfigDescription_test.cpp b/libs/androidfw/tests/ConfigDescription_test.cpp
similarity index 93%
rename from tools/aapt2/ConfigDescription_test.cpp
rename to libs/androidfw/tests/ConfigDescription_test.cpp
index 1f351bf..ce7f805 100644
--- a/tools/aapt2/ConfigDescription_test.cpp
+++ b/libs/androidfw/tests/ConfigDescription_test.cpp
@@ -14,18 +14,16 @@
* limitations under the License.
*/
-#include "ConfigDescription.h"
+#include "androidfw/ConfigDescription.h"
+#include "androidfw/StringPiece.h"
+
+#include "android-base/logging.h"
+
+#include "gtest/gtest.h"
#include <string>
-#include "androidfw/StringPiece.h"
-
-#include "SdkConstants.h"
-#include "test/Test.h"
-
-using android::StringPiece;
-
-namespace aapt {
+namespace android {
static ::testing::AssertionResult TestParse(
const StringPiece& input, ConfigDescription* config = nullptr) {
@@ -140,9 +138,13 @@
EXPECT_EQ(std::string("vrheadset-v26"), config.toString().string());
}
-TEST(ConfigDescriptionTest, RangeQualifiersDoNotConflict) {
- using test::ParseConfigOrDie;
+static inline ConfigDescription ParseConfigOrDie(const android::StringPiece& str) {
+ ConfigDescription config;
+ CHECK(ConfigDescription::Parse(str, &config)) << "invalid configuration: " << str;
+ return config;
+}
+TEST(ConfigDescriptionTest, RangeQualifiersDoNotConflict) {
EXPECT_FALSE(ParseConfigOrDie("large").ConflictsWith(ParseConfigOrDie("normal-land")));
EXPECT_FALSE(ParseConfigOrDie("long-hdpi").ConflictsWith(ParseConfigOrDie("xhdpi")));
EXPECT_FALSE(ParseConfigOrDie("sw600dp").ConflictsWith(ParseConfigOrDie("sw700dp")));
@@ -152,4 +154,4 @@
EXPECT_FALSE(ParseConfigOrDie("600x400").ConflictsWith(ParseConfigOrDie("300x200")));
}
-} // namespace aapt
+} // namespace android
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index cae632d..ffa4836 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -278,4 +278,52 @@
// sizeof(Res_value) might not be backwards compatible.
TEST(LoadedArscTest, LoadingShouldBeForwardsAndBackwardsCompatible) { ASSERT_TRUE(false); }
+TEST(LoadedArscTest, ResourceIdentifierIterator) {
+ std::string contents;
+ ASSERT_TRUE(
+ ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents));
+
+ std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
+ ASSERT_NE(nullptr, loaded_arsc);
+
+ const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc->GetPackages();
+ ASSERT_EQ(1u, packages.size());
+ EXPECT_EQ(std::string("com.android.basic"), packages[0]->GetPackageName());
+
+ const auto& loaded_package = packages[0];
+ auto iter = loaded_package->begin();
+ auto end = loaded_package->end();
+
+ ASSERT_NE(end, iter);
+ ASSERT_EQ(0x7f010000u, *iter++);
+ ASSERT_EQ(0x7f010001u, *iter++);
+ ASSERT_EQ(0x7f020000u, *iter++);
+ ASSERT_EQ(0x7f020001u, *iter++);
+ ASSERT_EQ(0x7f030000u, *iter++);
+ ASSERT_EQ(0x7f030001u, *iter++);
+ ASSERT_EQ(0x7f030002u, *iter++); // note: string without default, excluded by aapt2 dump
+ ASSERT_EQ(0x7f040000u, *iter++);
+ ASSERT_EQ(0x7f040001u, *iter++);
+ ASSERT_EQ(0x7f040002u, *iter++);
+ ASSERT_EQ(0x7f040003u, *iter++);
+ ASSERT_EQ(0x7f040004u, *iter++);
+ ASSERT_EQ(0x7f040005u, *iter++);
+ ASSERT_EQ(0x7f040006u, *iter++);
+ ASSERT_EQ(0x7f040007u, *iter++);
+ ASSERT_EQ(0x7f040008u, *iter++);
+ ASSERT_EQ(0x7f040009u, *iter++);
+ ASSERT_EQ(0x7f04000au, *iter++);
+ ASSERT_EQ(0x7f04000bu, *iter++);
+ ASSERT_EQ(0x7f04000cu, *iter++);
+ ASSERT_EQ(0x7f04000du, *iter++);
+ ASSERT_EQ(0x7f050000u, *iter++);
+ ASSERT_EQ(0x7f050001u, *iter++);
+ ASSERT_EQ(0x7f060000u, *iter++);
+ ASSERT_EQ(0x7f070000u, *iter++);
+ ASSERT_EQ(0x7f070001u, *iter++);
+ ASSERT_EQ(0x7f070002u, *iter++);
+ ASSERT_EQ(0x7f070003u, *iter++);
+ ASSERT_EQ(end, iter);
+}
+
} // namespace android
diff --git a/tools/aapt2/Locale_test.cpp b/libs/androidfw/tests/Locale_test.cpp
similarity index 96%
rename from tools/aapt2/Locale_test.cpp
rename to libs/androidfw/tests/Locale_test.cpp
index 68b4cae..6b2ef5f 100644
--- a/tools/aapt2/Locale_test.cpp
+++ b/libs/androidfw/tests/Locale_test.cpp
@@ -14,15 +14,14 @@
* limitations under the License.
*/
-#include "Locale.h"
+#include "androidfw/Locale.h"
+#include "androidfw/Util.h"
#include <string>
#include "gtest/gtest.h"
-#include "util/Util.h"
-
-namespace aapt {
+namespace android {
static ::testing::AssertionResult TestLanguage(const char* input,
const char* lang) {
@@ -93,4 +92,4 @@
EXPECT_TRUE(TestLanguageRegion("fr-rCA", "fr", "CA"));
}
-} // namespace aapt
+} // namespace android
diff --git a/libs/androidfw/tests/PosixUtils_test.cpp b/libs/androidfw/tests/PosixUtils_test.cpp
new file mode 100644
index 0000000..cf97f87
--- /dev/null
+++ b/libs/androidfw/tests/PosixUtils_test.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include <utility>
+
+#include "androidfw/PosixUtils.h"
+
+#include "TestHelpers.h"
+
+using ::testing::IsNull;
+using ::testing::NotNull;
+
+namespace android {
+namespace util {
+
+TEST(PosixUtilsTest, AbsolutePathToBinary) {
+ const auto result = ExecuteBinary({"/bin/date", "--help"});
+ ASSERT_THAT(result, NotNull());
+ ASSERT_EQ(result->status, 0);
+ ASSERT_EQ(result->stdout.find("usage: date "), 0);
+}
+
+TEST(PosixUtilsTest, RelativePathToBinary) {
+ const auto result = ExecuteBinary({"date", "--help"});
+ ASSERT_THAT(result, NotNull());
+ ASSERT_EQ(result->status, 0);
+ ASSERT_EQ(result->stdout.find("usage: date "), 0);
+}
+
+TEST(PosixUtilsTest, BadParameters) {
+ const auto result = ExecuteBinary({"/bin/date", "--this-parameter-is-not-supported"});
+ ASSERT_THAT(result, NotNull());
+ ASSERT_NE(result->status, 0);
+}
+
+TEST(PosixUtilsTest, NoSuchBinary) {
+ const auto result = ExecuteBinary({"/this/binary/does/not/exist"});
+ ASSERT_THAT(result, IsNull());
+}
+
+} // android
+} // util
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index e6d2a6f..f2d50cd 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -146,7 +146,7 @@
frame[FrameInfoIndex::IntendedVsync] + mFrameInterval);
// If we hit the deadline, cool!
- if (frame[FrameInfoIndex::FrameCompleted] < mSwapDeadline) {
+ if (frame[FrameInfoIndex::FrameCompleted] < mSwapDeadline || totalDuration < mFrameInterval) {
if (isTripleBuffered) {
mData->reportJankType(JankType::kHighInputLatency);
(*mGlobalData)->reportJankType(JankType::kHighInputLatency);
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 02e1f2f..2eed70f 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -159,8 +159,9 @@
public static final String SCANNED_BUILD_PREFS_NAME = "MediaScanBuild";
public static final String LAST_INTERNAL_SCAN_FINGERPRINT = "lastScanFingerprint";
- private static final String SYSTEM_SOUNDS_DIR = "/system/media/audio";
- private static final String PRODUCT_SOUNDS_DIR = "/product/media/audio";
+ private static final String SYSTEM_SOUNDS_DIR = Environment.getRootDirectory() + "/media/audio";
+ private static final String OEM_SOUNDS_DIR = Environment.getOemDirectory() + "/media/audio";
+ private static final String PRODUCT_SOUNDS_DIR = Environment.getProductDirectory() + "/media/audio";
private static String sLastInternalScanFingerprint;
private static final String[] ID3_GENRES = {
@@ -1192,6 +1193,9 @@
if (path.startsWith(SYSTEM_SOUNDS_DIR + ALARMS_DIR)
|| path.startsWith(SYSTEM_SOUNDS_DIR + RINGTONES_DIR)
|| path.startsWith(SYSTEM_SOUNDS_DIR + NOTIFICATIONS_DIR)
+ || path.startsWith(OEM_SOUNDS_DIR + ALARMS_DIR)
+ || path.startsWith(OEM_SOUNDS_DIR + RINGTONES_DIR)
+ || path.startsWith(OEM_SOUNDS_DIR + NOTIFICATIONS_DIR)
|| path.startsWith(PRODUCT_SOUNDS_DIR + ALARMS_DIR)
|| path.startsWith(PRODUCT_SOUNDS_DIR + RINGTONES_DIR)
|| path.startsWith(PRODUCT_SOUNDS_DIR + NOTIFICATIONS_DIR)) {
diff --git a/media/jni/OWNERS b/media/jni/OWNERS
new file mode 100644
index 0000000..bb91d4b
--- /dev/null
+++ b/media/jni/OWNERS
@@ -0,0 +1,2 @@
+# extra for MTP related files
+per-file android_mtp_*.cpp=marcone@google.com,jsharkey@android.com,jameswei@google.com,rmojumder@google.com
diff --git a/media/tests/MtpTests/OWNERS b/media/tests/MtpTests/OWNERS
new file mode 100644
index 0000000..1928ba8
--- /dev/null
+++ b/media/tests/MtpTests/OWNERS
@@ -0,0 +1,7 @@
+set noparent
+
+marcone@google.com
+jsharkey@android.com
+jameswei@google.com
+rmojumder@google.com
+
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index fd1212a..774a035 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -130,6 +130,22 @@
mProbeSpec = null;
}
+ mNetworkCallback = new NetworkCallback() {
+ @Override
+ public void onLost(Network lostNetwork) {
+ // If the network disappears while the app is up, exit.
+ if (mNetwork.equals(lostNetwork)) done(Result.UNWANTED);
+ }
+ };
+ mCm.registerNetworkCallback(new NetworkRequest.Builder().build(), mNetworkCallback);
+
+ // If the network has disappeared, exit.
+ final NetworkCapabilities networkCapabilities = mCm.getNetworkCapabilities(mNetwork);
+ if (networkCapabilities == null) {
+ finishAndRemoveTask();
+ return;
+ }
+
// Also initializes proxy system properties.
mNetwork = mNetwork.getPrivateDnsBypassingCopy();
mCm.bindProcessToNetwork(mNetwork);
@@ -139,24 +155,6 @@
// setContentView initializes the WebView logic which in turn reads the system properties.
setContentView(R.layout.activity_captive_portal_login);
- // Exit app if Network disappears.
- final NetworkCapabilities networkCapabilities = mCm.getNetworkCapabilities(mNetwork);
- if (networkCapabilities == null) {
- finishAndRemoveTask();
- return;
- }
- mNetworkCallback = new NetworkCallback() {
- @Override
- public void onLost(Network lostNetwork) {
- if (mNetwork.equals(lostNetwork)) done(Result.UNWANTED);
- }
- };
- final NetworkRequest.Builder builder = new NetworkRequest.Builder();
- for (int transportType : networkCapabilities.getTransportTypes()) {
- builder.addTransportType(transportType);
- }
- mCm.registerNetworkCallback(builder.build(), mNetworkCallback);
-
getActionBar().setDisplayShowHomeEnabled(false);
getActionBar().setElevation(0); // remove shadow
getActionBar().setTitle(getHeaderTitle());
diff --git a/packages/ExtServices/tests/AndroidTest.xml b/packages/ExtServices/tests/AndroidTest.xml
new file mode 100644
index 0000000..c3d32de
--- /dev/null
+++ b/packages/ExtServices/tests/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 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.
+-->
+<configuration description="Runs Tests for ExtServices">
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="ExtServicesUnitTests.apk" />
+ </target_preparer>
+
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="framework-base-presubmit" />
+ <option name="test-tag" value="ExtServicesUnitTests" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.ext.services.tests.unit" />
+ <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/packages/PrintSpooler/Android.bp b/packages/PrintSpooler/Android.bp
new file mode 100644
index 0000000..c40a81791
--- /dev/null
+++ b/packages/PrintSpooler/Android.bp
@@ -0,0 +1,38 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_app {
+ name: "PrintSpooler",
+
+ resource_dirs: ["res"],
+
+ srcs: [
+ "src/**/*.java",
+ "src/com/android/printspooler/renderer/IPdfRenderer.aidl",
+ "src/com/android/printspooler/renderer/IPdfEditor.aidl",
+ ],
+
+ platform_apis: true,
+
+ jni_libs: ["libprintspooler_jni"],
+ static_libs: [
+ "android-support-v7-recyclerview",
+ "android-support-compat",
+ "android-support-media-compat",
+ "android-support-core-utils",
+ "android-support-core-ui",
+ "android-support-fragment",
+ "android-support-annotations",
+ ],
+}
diff --git a/packages/PrintSpooler/Android.mk b/packages/PrintSpooler/Android.mk
deleted file mode 100644
index e356f38..0000000
--- a/packages/PrintSpooler/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (C) 2013 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_USE_AAPT2 := true
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SRC_FILES += \
- src/com/android/printspooler/renderer/IPdfRenderer.aidl \
- src/com/android/printspooler/renderer/IPdfEditor.aidl
-
-LOCAL_PACKAGE_NAME := PrintSpooler
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_JNI_SHARED_LIBRARIES := libprintspooler_jni
-LOCAL_STATIC_ANDROID_LIBRARIES := \
- android-support-v7-recyclerview \
- android-support-compat \
- android-support-media-compat \
- android-support-core-utils \
- android-support-core-ui \
- android-support-fragment
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- android-support-annotations
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/PrintSpooler/tests/Android.mk b/packages/PrintSpooler/tests/Android.mk
deleted file mode 100644
index 83e00ce..0000000
--- a/packages/PrintSpooler/tests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/PrintSpooler/tests/outofprocess/Android.bp b/packages/PrintSpooler/tests/outofprocess/Android.bp
new file mode 100644
index 0000000..e88074e
--- /dev/null
+++ b/packages/PrintSpooler/tests/outofprocess/Android.bp
@@ -0,0 +1,30 @@
+// 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.
+
+android_test {
+ name: "PrintSpoolerOutOfProcessTests",
+
+ srcs: ["src/**/*.java"],
+
+ libs: ["android.test.runner.stubs"],
+ static_libs: [
+ "android-support-test",
+ "ub-uiautomator",
+ "mockito-target-minus-junit4",
+ "print-test-util-lib",
+ ],
+
+ sdk_version: "test_current",
+ test_suites: ["device-tests"],
+}
diff --git a/packages/PrintSpooler/tests/outofprocess/Android.mk b/packages/PrintSpooler/tests/outofprocess/Android.mk
deleted file mode 100644
index 161a600..0000000
--- a/packages/PrintSpooler/tests/outofprocess/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-# 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ub-uiautomator mockito-target-minus-junit4 print-test-util-lib
-
-LOCAL_PACKAGE_NAME := PrintSpoolerOutOfProcessTests
-LOCAL_SDK_VERSION := current
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index a46c3e6..76a216d 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1125,4 +1125,7 @@
<!-- time label for event have that happened very recently [CHAR LIMIT=60] -->
<string name="time_unit_just_now">Just now</string>
+
+ <!-- The notice header of Third-party licenses. not translatable -->
+ <string name="notice_header" translatable="false"></string>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index 541877c..3c58160 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -105,7 +105,7 @@
BluetoothProfile.A2DP);
}
- public boolean isConnectable() {
+ public boolean accessProfileEnabled() {
return true;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
index 0e0f63c..656f23f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
@@ -99,7 +99,7 @@
BluetoothProfile.A2DP_SINK);
}
- public boolean isConnectable() {
+ public boolean accessProfileEnabled() {
return true;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index e96c44d..8fa9597 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -250,7 +250,7 @@
int preferredProfiles = 0;
for (LocalBluetoothProfile profile : mProfiles) {
- if (connectAllProfiles ? profile.isConnectable() : profile.isAutoConnectable()) {
+ if (connectAllProfiles ? profile.accessProfileEnabled() : profile.isAutoConnectable()) {
if (profile.isPreferred(mDevice)) {
++preferredProfiles;
connectInt(profile);
@@ -736,7 +736,7 @@
List<LocalBluetoothProfile> connectableProfiles =
new ArrayList<LocalBluetoothProfile>();
for (LocalBluetoothProfile profile : mProfiles) {
- if (profile.isConnectable()) {
+ if (profile.accessProfileEnabled()) {
connectableProfiles.add(profile);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
index 7f83860..3bb8450 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
@@ -106,7 +106,7 @@
BluetoothProfile.HEADSET);
}
- public boolean isConnectable() {
+ public boolean accessProfileEnabled() {
return true;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index 1d2fda9..06d60e6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -103,7 +103,7 @@
BluetoothProfile.HEARING_AID);
}
- public boolean isConnectable() {
+ public boolean accessProfileEnabled() {
return false;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
index 0857b01..4ae9b32 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
@@ -107,7 +107,7 @@
}
@Override
- public boolean isConnectable() {
+ public boolean accessProfileEnabled() {
return true;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java
index ca1eea5..1c04e83 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidDeviceProfile.java
@@ -29,7 +29,7 @@
import java.util.List;
/**
- * HidProfile handles Bluetooth HID profile.
+ * HidDeviceProfile handles Bluetooth HID Device role
*/
public class HidDeviceProfile implements LocalBluetoothProfile {
private static final String TAG = "HidDeviceProfile";
@@ -37,7 +37,6 @@
private static final int ORDINAL = 18;
// HID Device Profile is always preferred.
private static final int PREFERRED_VALUE = -1;
- private static final boolean DEBUG = true;
private final LocalBluetoothAdapter mLocalAdapter;
private final CachedBluetoothDeviceManager mDeviceManager;
@@ -62,9 +61,7 @@
implements BluetoothProfile.ServiceListener {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
- if (DEBUG) {
- Log.d(TAG,"Bluetooth service connected :-)");
- }
+ Log.d(TAG, "Bluetooth service connected :-), profile:" + profile);
mService = (BluetoothHidDevice) proxy;
// We just bound to the service, so refresh the UI for any connected HID devices.
List<BluetoothDevice> deviceList = mService.getConnectedDevices();
@@ -84,9 +81,7 @@
}
public void onServiceDisconnected(int profile) {
- if (DEBUG) {
- Log.d(TAG, "Bluetooth service disconnected");
- }
+ Log.d(TAG, "Bluetooth service disconnected, profile:" + profile);
mIsProfileReady = false;
}
}
@@ -102,7 +97,7 @@
}
@Override
- public boolean isConnectable() {
+ public boolean accessProfileEnabled() {
return true;
}
@@ -113,6 +108,7 @@
@Override
public boolean connect(BluetoothDevice device) {
+ // Don't invoke method in service because settings is not allowed to connect this profile.
return false;
}
@@ -129,11 +125,7 @@
if (mService == null) {
return BluetoothProfile.STATE_DISCONNECTED;
}
- List<BluetoothDevice> deviceList = mService.getConnectedDevices();
-
- return !deviceList.isEmpty() && deviceList.contains(device)
- ? mService.getConnectionState(device)
- : BluetoothProfile.STATE_DISCONNECTED;
+ return mService.getConnectionState(device);
}
@Override
@@ -188,9 +180,7 @@
}
protected void finalize() {
- if (DEBUG) {
- Log.d(TAG, "finalize()");
- }
+ Log.d(TAG, "finalize()");
if (mService != null) {
try {
BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.HID_DEVICE,
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
index dc17e44..1e06481 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
@@ -95,7 +95,7 @@
BluetoothProfile.HID_HOST);
}
- public boolean isConnectable() {
+ public boolean accessProfileEnabled() {
return true;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfile.java
index 0447f37..4b0ca74 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfile.java
@@ -26,9 +26,9 @@
public interface LocalBluetoothProfile {
/**
- * Returns true if the user can initiate a connection, false otherwise.
+ * Return {@code true} if the user can initiate a connection for this profile in UI.
*/
- boolean isConnectable();
+ boolean accessProfileEnabled();
/**
* Returns true if the user can enable auto connection for this profile.
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 08fbbed..75cbb65 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -29,6 +29,7 @@
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothPbap;
import android.bluetooth.BluetoothPbapClient;
+import android.bluetooth.BluetoothSap;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.content.Context;
@@ -101,6 +102,7 @@
private final boolean mUsePbapPce;
private final boolean mUseMapClient;
private HearingAidProfile mHearingAidProfile;
+ private SapProfile mSapProfile;
/**
* Mapping from profile name, e.g. "HEADSET" to profile object.
@@ -196,12 +198,14 @@
if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSink)) {
if (mA2dpSinkProfile == null) {
if(DEBUG) Log.d(TAG, "Adding local A2DP Sink profile");
- mA2dpSinkProfile = new A2dpSinkProfile(mContext, mLocalAdapter, mDeviceManager, this);
+ mA2dpSinkProfile = new A2dpSinkProfile(mContext, mLocalAdapter,
+ mDeviceManager, this);
addProfile(mA2dpSinkProfile, A2dpSinkProfile.NAME,
BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED);
}
} else if (mA2dpSinkProfile != null) {
- Log.w(TAG, "Warning: A2DP Sink profile was previously added but the UUID is now missing.");
+ Log.w(TAG, "Warning: A2DP Sink profile was previously added but the "
+ + "UUID is now missing.");
}
// Headset / Handsfree
@@ -217,7 +221,8 @@
BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
}
} else if (mHeadsetProfile != null) {
- Log.w(TAG, "Warning: HEADSET profile was previously added but the UUID is now missing.");
+ Log.w(TAG, "Warning: HEADSET profile was previously added but the "
+ + "UUID is now missing.");
}
// Headset HF
@@ -249,7 +254,8 @@
}
} else if (mMapClientProfile != null) {
Log.w(TAG,
- "Warning: MAP Client profile was previously added but the UUID is now missing.");
+ "Warning: MAP Client profile was previously added but the "
+ + "UUID is now missing.");
} else {
Log.d(TAG, "MAP Client Uuid not found.");
}
@@ -266,7 +272,7 @@
Log.w(TAG, "Warning: OPP profile was previously added but the UUID is now missing.");
}
- //PBAP Client
+ // PBAP Client
if (mUsePbapPce) {
if (mPbapClientProfile == null) {
if(DEBUG) Log.d(TAG, "Adding local PBAP Client profile");
@@ -280,18 +286,27 @@
"Warning: PBAP Client profile was previously added but the UUID is now missing.");
}
- //Hearing Aid Client
+ // Hearing Aid Client
if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HearingAid)) {
if (mHearingAidProfile == null) {
if(DEBUG) Log.d(TAG, "Adding local Hearing Aid profile");
- mHearingAidProfile = new HearingAidProfile(mContext, mLocalAdapter, mDeviceManager, this);
+ mHearingAidProfile = new HearingAidProfile(mContext, mLocalAdapter,
+ mDeviceManager, this);
addProfile(mHearingAidProfile, HearingAidProfile.NAME,
BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
}
} else if (mHearingAidProfile != null) {
- Log.w(TAG, "Warning: Hearing Aid profile was previously added but the UUID is now missing.");
+ Log.w(TAG, "Warning: Hearing Aid profile was previously added but the "
+ + "UUID is now missing.");
}
+ // SAP
+ if (mSapProfile == null && BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.SAP)) {
+ Log.d(TAG, "Adding local SAP profile");
+ mSapProfile = new SapProfile(mContext, mLocalAdapter, mDeviceManager, this);
+ addProfile(mSapProfile, SapProfile.NAME,
+ BluetoothSap.ACTION_CONNECTION_STATE_CHANGED);
+ }
mEventManager.registerProfileIntentReceiver();
// There is no local SDP record for HID and Settings app doesn't control PBAP Server.
@@ -635,6 +650,11 @@
removedProfiles.remove(mHearingAidProfile);
}
+ if (mSapProfile != null && BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.SAP)) {
+ profiles.add(mSapProfile);
+ removedProfiles.remove(mSapProfile);
+ }
+
if (DEBUG) {
Log.d(TAG,"New Profiles" + profiles.toString());
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
index ad0d8ba..57712e3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
@@ -32,11 +32,10 @@
import java.util.List;
/**
- * MapClientProfile handles Bluetooth MAP profile.
+ * MapClientProfile handles the Bluetooth MAP MCE role.
*/
public final class MapClientProfile implements LocalBluetoothProfile {
private static final String TAG = "MapClientProfile";
- private static boolean V = false;
private BluetoothMapClient mService;
private boolean mIsProfileReady;
@@ -61,7 +60,7 @@
implements BluetoothProfile.ServiceListener {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
- if (V) Log.d(TAG,"Bluetooth service connected");
+ Log.d(TAG, "Bluetooth service connected, profile:" + profile);
mService = (BluetoothMapClient) proxy;
// We just bound to the service, so refresh the UI for any connected MAP devices.
List<BluetoothDevice> deviceList = mService.getConnectedDevices();
@@ -83,14 +82,14 @@
}
public void onServiceDisconnected(int profile) {
- if (V) Log.d(TAG,"Bluetooth service disconnected");
+ Log.d(TAG, "Bluetooth service disconnected, profile:" + profile);
mProfileManager.callServiceDisconnectedListeners();
mIsProfileReady=false;
}
}
public boolean isProfileReady() {
- if(V) Log.d(TAG,"isProfileReady(): "+ mIsProfileReady);
+ Log.d(TAG, "isProfileReady(): "+ mIsProfileReady);
return mIsProfileReady;
}
@@ -109,7 +108,7 @@
BluetoothProfile.MAP_CLIENT);
}
- public boolean isConnectable() {
+ public boolean accessProfileEnabled() {
return true;
}
@@ -118,18 +117,16 @@
}
public boolean connect(BluetoothDevice device) {
- if (mService == null) return false;
- List<BluetoothDevice> connectedDevices = getConnectedDevices();
- if (connectedDevices != null && connectedDevices.contains(device)) {
- // Connect to same device, Ignore it
- Log.d(TAG,"Ignoring Connect");
- return true;
+ if (mService == null) {
+ return false;
}
return mService.connect(device);
}
public boolean disconnect(BluetoothDevice device) {
- if (mService == null) return false;
+ if (mService == null) {
+ return false;
+ }
// Downgrade priority as user is disconnecting.
if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
@@ -138,23 +135,30 @@
}
public int getConnectionStatus(BluetoothDevice device) {
- if (mService == null) return BluetoothProfile.STATE_DISCONNECTED;
-
+ if (mService == null) {
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
return mService.getConnectionState(device);
}
public boolean isPreferred(BluetoothDevice device) {
- if (mService == null) return false;
+ if (mService == null) {
+ return false;
+ }
return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
}
public int getPreferred(BluetoothDevice device) {
- if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+ if (mService == null) {
+ return BluetoothProfile.PRIORITY_OFF;
+ }
return mService.getPriority(device);
}
public void setPreferred(BluetoothDevice device, boolean preferred) {
- if (mService == null) return;
+ if (mService == null) {
+ return;
+ }
if (preferred) {
if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
@@ -165,7 +169,9 @@
}
public List<BluetoothDevice> getConnectedDevices() {
- if (mService == null) return new ArrayList<BluetoothDevice>(0);
+ if (mService == null) {
+ return new ArrayList<BluetoothDevice>(0);
+ }
return mService.getDevicesMatchingConnectionStates(
new int[] {BluetoothProfile.STATE_CONNECTED,
BluetoothProfile.STATE_CONNECTING,
@@ -203,11 +209,11 @@
}
protected void finalize() {
- if (V) Log.d(TAG, "finalize()");
+ Log.d(TAG, "finalize()");
if (mService != null) {
try {
BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.MAP_CLIENT,
- mService);
+ mService);
mService = null;
}catch (Throwable t) {
Log.w(TAG, "Error cleaning up MAP Client proxy", t);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
index 511c4ce..e59a036 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapProfile.java
@@ -107,7 +107,7 @@
BluetoothProfile.MAP);
}
- public boolean isConnectable() {
+ public boolean accessProfileEnabled() {
return true;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java
index dfd1622..e1e5dbe 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/OppProfile.java
@@ -32,7 +32,7 @@
// Order of this profile in device profiles list
private static final int ORDINAL = 2;
- public boolean isConnectable() {
+ public boolean accessProfileEnabled() {
return false;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java
index b18b19b..0d566c7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PanProfile.java
@@ -80,7 +80,7 @@
BluetoothProfile.PAN);
}
- public boolean isConnectable() {
+ public boolean accessProfileEnabled() {
return true;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
index bdbfc9d..c83ff35 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
@@ -34,7 +34,6 @@
public final class PbapClientProfile implements LocalBluetoothProfile {
private static final String TAG = "PbapClientProfile";
- private static boolean V = false;
private BluetoothPbapClient mService;
private boolean mIsProfileReady;
@@ -57,9 +56,7 @@
implements BluetoothProfile.ServiceListener {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
- if (V) {
- Log.d(TAG,"Bluetooth service connected");
- }
+ Log.d(TAG, "Bluetooth service connected, profile:" + profile);
mService = (BluetoothPbapClient) proxy;
// We just bound to the service, so refresh the UI for any connected PBAP devices.
List<BluetoothDevice> deviceList = mService.getConnectedDevices();
@@ -78,9 +75,7 @@
}
public void onServiceDisconnected(int profile) {
- if (V) {
- Log.d(TAG,"Bluetooth service disconnected");
- }
+ Log.d(TAG, "Bluetooth service disconnected, profile:" + profile);
mIsProfileReady = false;
}
}
@@ -115,7 +110,7 @@
BluetoothProfile.PBAP_CLIENT);
}
- public boolean isConnectable() {
+ public boolean accessProfileEnabled() {
return true;
}
@@ -134,31 +129,16 @@
}
public boolean connect(BluetoothDevice device) {
- if (V) {
- Log.d(TAG,"PBAPClientProfile got connect request");
- }
+ Log.d(TAG,"PBAPClientProfile got connect request");
if (mService == null) {
return false;
}
- List<BluetoothDevice> srcs = getConnectedDevices();
- if (srcs != null) {
- for (BluetoothDevice src : srcs) {
- if (src.equals(device)) {
- // Connect to same device, Ignore it
- Log.d(TAG,"Ignoring Connect");
- return true;
- }
- }
- }
Log.d(TAG,"PBAPClientProfile attempting to connect to " + device.getAddress());
-
return mService.connect(device);
}
public boolean disconnect(BluetoothDevice device) {
- if (V) {
- Log.d(TAG,"PBAPClientProfile got disconnect request");
- }
+ Log.d(TAG,"PBAPClientProfile got disconnect request");
if (mService == null) {
return false;
}
@@ -221,9 +201,7 @@
}
protected void finalize() {
- if (V) {
- Log.d(TAG, "finalize()");
- }
+ Log.d(TAG, "finalize()");
if (mService != null) {
try {
BluetoothAdapter.getDefaultAdapter().closeProfileProxy(
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java
index e9d8cb5..adef0841 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapServerProfile.java
@@ -80,7 +80,7 @@
BluetoothPbap pbap = new BluetoothPbap(context, new PbapServiceListener());
}
- public boolean isConnectable() {
+ public boolean accessProfileEnabled() {
return true;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
index 2c455d5f..e83c62d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
@@ -36,7 +36,6 @@
*/
final class SapProfile implements LocalBluetoothProfile {
private static final String TAG = "SapProfile";
- private static boolean V = true;
private BluetoothSap mService;
private boolean mIsProfileReady;
@@ -59,7 +58,7 @@
implements BluetoothProfile.ServiceListener {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
- if (V) Log.d(TAG,"Bluetooth service connected");
+ Log.d(TAG, "Bluetooth service connected, profile:" + profile);
mService = (BluetoothSap) proxy;
// We just bound to the service, so refresh the UI for any connected SAP devices.
List<BluetoothDevice> deviceList = mService.getConnectedDevices();
@@ -81,7 +80,7 @@
}
public void onServiceDisconnected(int profile) {
- if (V) Log.d(TAG,"Bluetooth service disconnected");
+ Log.d(TAG, "Bluetooth service disconnected, profile:" + profile);
mProfileManager.callServiceDisconnectedListeners();
mIsProfileReady=false;
}
@@ -106,7 +105,7 @@
BluetoothProfile.SAP);
}
- public boolean isConnectable() {
+ public boolean accessProfileEnabled() {
return true;
}
@@ -115,50 +114,47 @@
}
public boolean connect(BluetoothDevice device) {
- if (mService == null) return false;
- List<BluetoothDevice> sinks = mService.getConnectedDevices();
- if (sinks != null) {
- for (BluetoothDevice sink : sinks) {
- mService.disconnect(sink);
- }
+ if (mService == null) {
+ return false;
}
return mService.connect(device);
}
public boolean disconnect(BluetoothDevice device) {
- if (mService == null) return false;
- List<BluetoothDevice> deviceList = mService.getConnectedDevices();
- if (!deviceList.isEmpty() && deviceList.get(0).equals(device)) {
- if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
- mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
- }
- return mService.disconnect(device);
- } else {
+ if (mService == null) {
return false;
}
+ if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+ return mService.disconnect(device);
}
public int getConnectionStatus(BluetoothDevice device) {
- if (mService == null) return BluetoothProfile.STATE_DISCONNECTED;
- List<BluetoothDevice> deviceList = mService.getConnectedDevices();
-
- return !deviceList.isEmpty() && deviceList.get(0).equals(device)
- ? mService.getConnectionState(device)
- : BluetoothProfile.STATE_DISCONNECTED;
+ if (mService == null) {
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ return mService.getConnectionState(device);
}
public boolean isPreferred(BluetoothDevice device) {
- if (mService == null) return false;
+ if (mService == null) {
+ return false;
+ }
return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
}
public int getPreferred(BluetoothDevice device) {
- if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+ if (mService == null) {
+ return BluetoothProfile.PRIORITY_OFF;
+ }
return mService.getPriority(device);
}
public void setPreferred(BluetoothDevice device, boolean preferred) {
- if (mService == null) return;
+ if (mService == null) {
+ return;
+ }
if (preferred) {
if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
@@ -169,7 +165,9 @@
}
public List<BluetoothDevice> getConnectedDevices() {
- if (mService == null) return new ArrayList<BluetoothDevice>(0);
+ if (mService == null) {
+ return new ArrayList<BluetoothDevice>(0);
+ }
return mService.getDevicesMatchingConnectionStates(
new int[] {BluetoothProfile.STATE_CONNECTED,
BluetoothProfile.STATE_CONNECTING,
@@ -207,11 +205,11 @@
}
protected void finalize() {
- if (V) Log.d(TAG, "finalize()");
+ Log.d(TAG, "finalize()");
if (mService != null) {
try {
BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.SAP,
- mService);
+ mService);
mService = null;
}catch (Throwable t) {
Log.w(TAG, "Error cleaning up SAP proxy", t);
diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
index 42306f6..9870b3c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
+++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
@@ -107,12 +107,13 @@
mXmlFiles = xmlFiles;
}
- public static boolean generateHtml(List<File> xmlFiles, File outputFile) {
+ public static boolean generateHtml(List<File> xmlFiles, File outputFile,
+ String noticeHeader) {
LicenseHtmlGeneratorFromXml genertor = new LicenseHtmlGeneratorFromXml(xmlFiles);
- return genertor.generateHtml(outputFile);
+ return genertor.generateHtml(outputFile, noticeHeader);
}
- private boolean generateHtml(File outputFile) {
+ private boolean generateHtml(File outputFile, String noticeHeader) {
for (File xmlFile : mXmlFiles) {
parse(xmlFile);
}
@@ -125,7 +126,8 @@
try {
writer = new PrintWriter(outputFile);
- generateHtml(mFileNameToContentIdMap, mContentIdToFileContentMap, writer);
+ generateHtml(mFileNameToContentIdMap, mContentIdToFileContentMap, writer,
+ noticeHeader);
writer.flush();
writer.close();
@@ -239,13 +241,18 @@
@VisibleForTesting
static void generateHtml(Map<String, String> fileNameToContentIdMap,
- Map<String, String> contentIdToFileContentMap, PrintWriter writer) {
+ Map<String, String> contentIdToFileContentMap, PrintWriter writer,
+ String noticeHeader) {
List<String> fileNameList = new ArrayList();
fileNameList.addAll(fileNameToContentIdMap.keySet());
Collections.sort(fileNameList);
writer.println(HTML_HEAD_STRING);
+ if (!TextUtils.isEmpty(noticeHeader)) {
+ writer.println(noticeHeader);
+ }
+
int count = 0;
Map<String, Integer> contentIdToOrderMap = new HashMap();
List<ContentIdAndFileNames> contentIdAndFileNamesList = new ArrayList();
diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoader.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoader.java
index 2aaea65..8b562f70 100644
--- a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoader.java
@@ -21,6 +21,7 @@
import androidx.annotation.VisibleForTesting;
+import com.android.settingslib.R;
import com.android.settingslib.utils.AsyncLoader;
import java.io.File;
@@ -108,6 +109,7 @@
@VisibleForTesting
boolean generateHtmlFile(List<File> xmlFiles, File htmlFile) {
- return LicenseHtmlGeneratorFromXml.generateHtml(xmlFiles, htmlFile);
+ return LicenseHtmlGeneratorFromXml.generateHtml(xmlFiles, htmlFile,
+ mContext.getString(R.string.notice_header));
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HidDeviceProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HidDeviceProfileTest.java
new file mode 100644
index 0000000..354d926
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HidDeviceProfileTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 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 com.android.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHidDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class HidDeviceProfileTest {
+
+ @Mock
+ private LocalBluetoothAdapter mAdapter;
+ @Mock
+ private CachedBluetoothDeviceManager mDeviceManager;
+ @Mock
+ private LocalBluetoothProfileManager mProfileManager;
+ @Mock
+ private BluetoothHidDevice mService;
+ @Mock
+ private CachedBluetoothDevice mCachedBluetoothDevice;
+ @Mock
+ private BluetoothDevice mBluetoothDevice;
+ private BluetoothProfile.ServiceListener mServiceListener;
+ private HidDeviceProfile mProfile;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ doAnswer((invocation) -> {
+ mServiceListener = (BluetoothProfile.ServiceListener) invocation.getArguments()[1];
+ return null;
+ }).when(mAdapter).getProfileProxy(any(Context.class),
+ any(BluetoothProfile.ServiceListener.class), eq(BluetoothProfile.HID_DEVICE));
+
+ mProfile = new HidDeviceProfile(RuntimeEnvironment.application, mAdapter,
+ mDeviceManager, mProfileManager);
+ mServiceListener.onServiceConnected(BluetoothProfile.HID_DEVICE, mService);
+ }
+
+ @Test
+ public void connect_shouldReturnFalse() {
+ assertThat(mProfile.connect(mBluetoothDevice)).isFalse();
+ }
+
+ @Test
+ public void disconnect_shouldDisconnectBluetoothHidDevice() {
+ mProfile.disconnect(mBluetoothDevice);
+ verify(mService).disconnect(mBluetoothDevice);
+ }
+
+ @Test
+ public void getConnectionStatus_shouldReturnConnectionState() {
+ when(mService.getConnectionState(mBluetoothDevice)).
+ thenReturn(BluetoothProfile.STATE_CONNECTED);
+ assertThat(mProfile.getConnectionStatus(mBluetoothDevice)).
+ isEqualTo(BluetoothProfile.STATE_CONNECTED);
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/MapClientProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/MapClientProfileTest.java
new file mode 100644
index 0000000..97c9f18
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/MapClientProfileTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 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 com.android.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothMapClient;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class MapClientProfileTest {
+
+ @Mock
+ private LocalBluetoothAdapter mAdapter;
+ @Mock
+ private CachedBluetoothDeviceManager mDeviceManager;
+ @Mock
+ private LocalBluetoothProfileManager mProfileManager;
+ @Mock
+ private BluetoothMapClient mService;
+ @Mock
+ private CachedBluetoothDevice mCachedBluetoothDevice;
+ @Mock
+ private BluetoothDevice mBluetoothDevice;
+ private BluetoothProfile.ServiceListener mServiceListener;
+ private MapClientProfile mProfile;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ doAnswer((invocation) -> {
+ mServiceListener = (BluetoothProfile.ServiceListener) invocation.getArguments()[1];
+ return null;
+ }).when(mAdapter).getProfileProxy(any(Context.class),
+ any(BluetoothProfile.ServiceListener.class), eq(BluetoothProfile.MAP_CLIENT));
+
+ mProfile = new MapClientProfile(RuntimeEnvironment.application, mAdapter,
+ mDeviceManager, mProfileManager);
+ mServiceListener.onServiceConnected(BluetoothProfile.MAP_CLIENT, mService);
+ }
+
+ @Test
+ public void connect_shouldConnectBluetoothMapClient() {
+ mProfile.connect(mBluetoothDevice);
+ verify(mService).connect(mBluetoothDevice);
+ }
+
+ @Test
+ public void disconnect_shouldDisconnectBluetoothMapClient() {
+ mProfile.disconnect(mBluetoothDevice);
+ verify(mService).disconnect(mBluetoothDevice);
+ }
+
+ @Test
+ public void getConnectionStatus_shouldReturnConnectionState() {
+ when(mService.getConnectionState(mBluetoothDevice)).
+ thenReturn(BluetoothProfile.STATE_CONNECTED);
+ assertThat(mProfile.getConnectionStatus(mBluetoothDevice)).
+ isEqualTo(BluetoothProfile.STATE_CONNECTED);
+ }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/PbapClientProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/PbapClientProfileTest.java
new file mode 100644
index 0000000..45b52b2
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/PbapClientProfileTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 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 com.android.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothPbapClient;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class PbapClientProfileTest {
+
+ @Mock
+ private LocalBluetoothAdapter mAdapter;
+ @Mock
+ private CachedBluetoothDeviceManager mDeviceManager;
+ @Mock
+ private LocalBluetoothProfileManager mProfileManager;
+ @Mock
+ private BluetoothPbapClient mService;
+ @Mock
+ private CachedBluetoothDevice mCachedBluetoothDevice;
+ @Mock
+ private BluetoothDevice mBluetoothDevice;
+ private BluetoothProfile.ServiceListener mServiceListener;
+ private PbapClientProfile mProfile;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ doAnswer((invocation) -> {
+ mServiceListener = (BluetoothProfile.ServiceListener) invocation.getArguments()[1];
+ return null;
+ }).when(mAdapter).getProfileProxy(any(Context.class),
+ any(BluetoothProfile.ServiceListener.class), eq(BluetoothProfile.PBAP_CLIENT));
+
+ mProfile = new PbapClientProfile(RuntimeEnvironment.application, mAdapter,
+ mDeviceManager, mProfileManager);
+ mServiceListener.onServiceConnected(BluetoothProfile.PBAP_CLIENT, mService);
+ }
+
+ @Test
+ public void connect_shouldConnectBluetoothPbapClient() {
+ mProfile.connect(mBluetoothDevice);
+ verify(mService).connect(mBluetoothDevice);
+ }
+
+ @Test
+ public void disconnect_shouldDisconnectBluetoothPbapClient() {
+ mProfile.disconnect(mBluetoothDevice);
+ verify(mService).disconnect(mBluetoothDevice);
+ }
+
+ @Test
+ public void getConnectionStatus_shouldReturnConnectionState() {
+ when(mService.getConnectionState(mBluetoothDevice)).
+ thenReturn(BluetoothProfile.STATE_CONNECTED);
+ assertThat(mProfile.getConnectionStatus(mBluetoothDevice)).
+ isEqualTo(BluetoothProfile.STATE_CONNECTED);
+ }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/SapProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/SapProfileTest.java
new file mode 100644
index 0000000..6ff3e70
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/SapProfileTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 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 com.android.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothSap;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class SapProfileTest {
+
+ @Mock
+ private LocalBluetoothAdapter mAdapter;
+ @Mock
+ private CachedBluetoothDeviceManager mDeviceManager;
+ @Mock
+ private LocalBluetoothProfileManager mProfileManager;
+ @Mock
+ private BluetoothSap mService;
+ @Mock
+ private CachedBluetoothDevice mCachedBluetoothDevice;
+ @Mock
+ private BluetoothDevice mBluetoothDevice;
+ private BluetoothProfile.ServiceListener mServiceListener;
+ private SapProfile mProfile;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ doAnswer((invocation) -> {
+ mServiceListener = (BluetoothProfile.ServiceListener) invocation.getArguments()[1];
+ return null;
+ }).when(mAdapter).getProfileProxy(any(Context.class),
+ any(BluetoothProfile.ServiceListener.class), eq(BluetoothProfile.SAP));
+
+ mProfile = new SapProfile(RuntimeEnvironment.application, mAdapter,
+ mDeviceManager, mProfileManager);
+ mServiceListener.onServiceConnected(BluetoothProfile.SAP, mService);
+ }
+
+ @Test
+ public void connect_shouldConnectBluetoothSap() {
+ mProfile.connect(mBluetoothDevice);
+ verify(mService).connect(mBluetoothDevice);
+ }
+
+ @Test
+ public void disconnect_shouldDisconnectBluetoothSap() {
+ mProfile.disconnect(mBluetoothDevice);
+ verify(mService).disconnect(mBluetoothDevice);
+ }
+
+ @Test
+ public void getConnectionStatus_shouldReturnConnectionState() {
+ when(mService.getConnectionState(mBluetoothDevice)).
+ thenReturn(BluetoothProfile.STATE_CONNECTED);
+ assertThat(mProfile.getConnectionStatus(mBluetoothDevice)).
+ isEqualTo(BluetoothProfile.STATE_CONNECTED);
+ }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
index 96b2a14..b00476b2 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
@@ -50,7 +50,7 @@
+ "<file-content contentId=\"0\"><![CDATA[license content #0]]></file-content>\n"
+ "</licenses2>";
- private static final String EXPECTED_HTML_STRING =
+ private static final String HTML_HEAD_STRING =
"<html><head>\n"
+ "<style type=\"text/css\">\n"
+ "body { padding: 0; font-family: sans-serif; }\n"
@@ -63,8 +63,12 @@
+ "</head>"
+ "<body topmargin=\"0\" leftmargin=\"0\" rightmargin=\"0\" bottommargin=\"0\">\n"
+ "<div class=\"toc\">\n"
- + "<ul>\n"
- + "<li><a href=\"#id0\">/file0</a></li>\n"
+ + "<ul>\n";
+
+ private static final String HTML_CUSTOM_HEADING = "Custom heading";
+
+ private static final String HTML_BODY_STRING =
+ "<li><a href=\"#id0\">/file0</a></li>\n"
+ "<li><a href=\"#id0\">/file1</a></li>\n"
+ "</ul>\n"
+ "</div><!-- table of contents -->\n"
@@ -81,6 +85,11 @@
+ "</td></tr><!-- same-license -->\n"
+ "</table></body></html>\n";
+ private static final String EXPECTED_HTML_STRING = HTML_HEAD_STRING + HTML_BODY_STRING;
+
+ private static final String EXPECTED_HTML_STRING_WITH_CUSTOM_HEADING =
+ HTML_HEAD_STRING + HTML_CUSTOM_HEADING + "\n" + HTML_BODY_STRING;
+
@Test
public void testParseValidXmlStream() throws XmlPullParserException, IOException {
Map<String, String> fileNameToContentIdMap = new HashMap<String, String>();
@@ -117,7 +126,23 @@
StringWriter output = new StringWriter();
LicenseHtmlGeneratorFromXml.generateHtml(
- fileNameToContentIdMap, contentIdToFileContentMap, new PrintWriter(output));
+ fileNameToContentIdMap, contentIdToFileContentMap, new PrintWriter(output), "");
assertThat(output.toString()).isEqualTo(EXPECTED_HTML_STRING);
}
+
+ @Test
+ public void testGenerateHtmlWithCustomHeading() {
+ Map<String, String> fileNameToContentIdMap = new HashMap<String, String>();
+ Map<String, String> contentIdToFileContentMap = new HashMap<String, String>();
+
+ fileNameToContentIdMap.put("/file0", "0");
+ fileNameToContentIdMap.put("/file1", "0");
+ contentIdToFileContentMap.put("0", "license content #0");
+
+ StringWriter output = new StringWriter();
+ LicenseHtmlGeneratorFromXml.generateHtml(
+ fileNameToContentIdMap, contentIdToFileContentMap, new PrintWriter(output),
+ HTML_CUSTOM_HEADING);
+ assertThat(output.toString()).isEqualTo(EXPECTED_HTML_STRING_WITH_CUSTOM_HEADING);
+ }
}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 8a5cb4a..a090f6d 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -26,6 +26,7 @@
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
+ <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 4fc190d..2530abc 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -16,6 +16,8 @@
package com.android.shell;
+import static android.content.pm.PackageManager.FEATURE_LEANBACK;
+import static android.content.pm.PackageManager.FEATURE_TELEVISION;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
import static com.android.shell.BugreportPrefs.STATE_HIDE;
@@ -42,6 +44,7 @@
import libcore.io.Streams;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ChooserActivity;
import com.android.internal.logging.MetricsLogger;
@@ -232,9 +235,11 @@
*/
private boolean mTakingScreenshot;
+ @GuardedBy("sNotificationBundle")
private static final Bundle sNotificationBundle = new Bundle();
private boolean mIsWatch;
+ private boolean mIsTv;
private int mLastProgressPercent;
@@ -255,6 +260,9 @@
final Configuration conf = mContext.getResources().getConfiguration();
mIsWatch = (conf.uiMode & Configuration.UI_MODE_TYPE_MASK) ==
Configuration.UI_MODE_TYPE_WATCH;
+ PackageManager packageManager = getPackageManager();
+ mIsTv = packageManager.hasSystemFeature(FEATURE_LEANBACK)
+ || packageManager.hasSystemFeature(FEATURE_TELEVISION);
NotificationManager nm = NotificationManager.from(mContext);
nm.createNotificationChannel(
new NotificationChannel(NOTIFICATION_CHANNEL_ID,
@@ -500,8 +508,8 @@
.setProgress(info.max, info.progress, false)
.setOngoing(true);
- // Wear bugreport doesn't need the bug info dialog, screenshot and cancel action.
- if (!mIsWatch) {
+ // Wear and ATV bugreport doesn't need the bug info dialog, screenshot and cancel action.
+ if (!(mIsWatch || mIsTv)) {
final Action cancelAction = new Action.Builder(null, mContext.getString(
com.android.internal.R.string.cancel), newCancelIntent(mContext, info)).build();
final Intent infoIntent = new Intent(mContext, BugreportProgressService.class);
@@ -1053,10 +1061,12 @@
}
private static Notification.Builder newBaseNotification(Context context) {
- if (sNotificationBundle.isEmpty()) {
- // Rename notifcations from "Shell" to "Android System"
- sNotificationBundle.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
- context.getString(com.android.internal.R.string.android_system_label));
+ synchronized (sNotificationBundle) {
+ if (sNotificationBundle.isEmpty()) {
+ // Rename notifcations from "Shell" to "Android System"
+ sNotificationBundle.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
+ context.getString(com.android.internal.R.string.android_system_label));
+ }
}
return new Notification.Builder(context, NOTIFICATION_CHANNEL_ID)
.addExtras(sNotificationBundle)
diff --git a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
index 0734e0d..4fbc226 100644
--- a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
+++ b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
@@ -20,6 +20,7 @@
import android.database.MatrixCursor;
import android.database.MatrixCursor.RowBuilder;
import android.net.Uri;
+import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
@@ -68,6 +69,18 @@
}
@Override
+ public Cursor queryChildDocuments(
+ String parentDocumentId, String[] projection, String sortOrder)
+ throws FileNotFoundException {
+ final Cursor c = super.queryChildDocuments(parentDocumentId, projection, sortOrder);
+ final Bundle extras = new Bundle();
+ extras.putCharSequence(DocumentsContract.EXTRA_INFO,
+ getContext().getText(R.string.bugreport_confirm));
+ c.setExtras(extras);
+ return c;
+ }
+
+ @Override
public Cursor queryDocument(String documentId, String[] projection)
throws FileNotFoundException {
if (DOC_ID_ROOT.equals(documentId)) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java
index cd831d1..0c498bb 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java
@@ -24,8 +24,6 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import sun.misc.Resource;
-
public class NavigationBarCompat {
/**
* Touch slopes and thresholds for quick step operations. Drag slop is the point where the
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 9e4810c..35abb0a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -342,12 +342,11 @@
case SimPuk:
// Shortcut for SIM PIN/PUK to go to directly to user's security screen or home
SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId);
- if (securityMode != SecurityMode.None
- || !mLockPatternUtils.isLockScreenDisabled(
+ if (securityMode == SecurityMode.None || mLockPatternUtils.isLockScreenDisabled(
KeyguardUpdateMonitor.getCurrentUser())) {
- showSecurityScreen(securityMode);
- } else {
finish = true;
+ } else {
+ showSecurityScreen(securityMode);
}
break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index 2031b27..1fefa18 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -53,6 +53,7 @@
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
+ private final Object mCallbacksLock = new Object();
private final Context mContext;
private final GlobalSetting mModeSetting;
private final GlobalSetting mConfigSetting;
@@ -113,16 +114,20 @@
@Override
public void addCallback(Callback callback) {
- if (callback == null) {
- Slog.e(TAG, "Attempted to add a null callback.");
- return;
+ synchronized (mCallbacksLock) {
+ if (callback == null) {
+ Slog.e(TAG, "Attempted to add a null callback.");
+ return;
+ }
+ mCallbacks.add(callback);
}
- mCallbacks.add(callback);
}
@Override
public void removeCallback(Callback callback) {
- mCallbacks.remove(callback);
+ synchronized (mCallbacksLock) {
+ mCallbacks.remove(callback);
+ }
}
@Override
@@ -186,28 +191,40 @@
}
private void fireNextAlarmChanged() {
- Utils.safeForeach(mCallbacks, c -> c.onNextAlarmChanged());
+ synchronized (mCallbacksLock) {
+ Utils.safeForeach(mCallbacks, c -> c.onNextAlarmChanged());
+ }
}
private void fireEffectsSuppressorChanged() {
- Utils.safeForeach(mCallbacks, c -> c.onEffectsSupressorChanged());
+ synchronized (mCallbacksLock) {
+ Utils.safeForeach(mCallbacks, c -> c.onEffectsSupressorChanged());
+ }
}
private void fireZenChanged(int zen) {
- Utils.safeForeach(mCallbacks, c -> c.onZenChanged(zen));
+ synchronized (mCallbacksLock) {
+ Utils.safeForeach(mCallbacks, c -> c.onZenChanged(zen));
+ }
}
private void fireZenAvailableChanged(boolean available) {
- Utils.safeForeach(mCallbacks, c -> c.onZenAvailableChanged(available));
+ synchronized (mCallbacksLock) {
+ Utils.safeForeach(mCallbacks, c -> c.onZenAvailableChanged(available));
+ }
}
private void fireManualRuleChanged(ZenRule rule) {
- Utils.safeForeach(mCallbacks, c -> c.onManualRuleChanged(rule));
+ synchronized (mCallbacksLock) {
+ Utils.safeForeach(mCallbacks, c -> c.onManualRuleChanged(rule));
+ }
}
@VisibleForTesting
protected void fireConfigChanged(ZenModeConfig config) {
- Utils.safeForeach(mCallbacks, c -> c.onConfigChanged(config));
+ synchronized (mCallbacksLock) {
+ Utils.safeForeach(mCallbacks, c -> c.onConfigChanged(config));
+ }
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 7602090..5e8ffb7 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -35,6 +35,9 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
+import static android.os.Process.INVALID_UID;
+import static android.system.OsConstants.IPPROTO_TCP;
+import static android.system.OsConstants.IPPROTO_UDP;
import static com.android.internal.util.Preconditions.checkNotNull;
@@ -49,10 +52,12 @@
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.database.ContentObserver;
+import android.net.ConnectionInfo;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.PacketKeepalive;
import android.net.IConnectivityManager;
import android.net.IIpConnectivityMetrics;
+import android.net.INetd;
import android.net.INetdEventCallback;
import android.net.INetworkManagementEventObserver;
import android.net.INetworkPolicyListener;
@@ -75,7 +80,6 @@
import android.net.NetworkState;
import android.net.NetworkUtils;
import android.net.NetworkWatchlistManager;
-import android.net.Proxy;
import android.net.ProxyInfo;
import android.net.RouteInfo;
import android.net.UidRange;
@@ -83,7 +87,9 @@
import android.net.VpnService;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.NetworkEvent;
+import android.net.netlink.InetDiagMessage;
import android.net.util.MultinetworkPolicyTracker;
+import android.net.util.NetdService;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -153,7 +159,6 @@
import com.android.server.connectivity.NetworkMonitor;
import com.android.server.connectivity.NetworkNotificationManager;
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
-import com.android.server.connectivity.PacManager;
import com.android.server.connectivity.PermissionMonitor;
import com.android.server.connectivity.ProxyTracker;
import com.android.server.connectivity.Tethering;
@@ -256,7 +261,8 @@
// 0 is full bad, 100 is full good
private int mDefaultInetConditionPublished = 0;
- private INetworkManagementService mNetd;
+ private INetworkManagementService mNMS;
+ private INetd mNetd;
private INetworkStatsService mStatsService;
private INetworkPolicyManager mPolicyManager;
private NetworkPolicyManagerInternal mPolicyManagerInternal;
@@ -387,9 +393,9 @@
private static final int EVENT_PROMPT_UNVALIDATED = 29;
/**
- * used internally to (re)configure mobile data always-on settings.
+ * used internally to (re)configure always-on networks.
*/
- private static final int EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON = 30;
+ private static final int EVENT_CONFIGURE_ALWAYS_ON_NETWORKS = 30;
/**
* used to add a network listener with a pending intent
@@ -745,6 +751,12 @@
mDefaultMobileDataRequest = createDefaultInternetRequestForTransport(
NetworkCapabilities.TRANSPORT_CELLULAR, NetworkRequest.Type.BACKGROUND_REQUEST);
+ // The default WiFi request is a background request so that apps using WiFi are
+ // migrated to a better network (typically ethernet) when one comes up, instead
+ // of staying on WiFi forever.
+ mDefaultWifiRequest = createDefaultInternetRequestForTransport(
+ NetworkCapabilities.TRANSPORT_WIFI, NetworkRequest.Type.BACKGROUND_REQUEST);
+
mHandlerThread = new HandlerThread("ConnectivityServiceThread");
mHandlerThread.start();
mHandler = new InternalHandler(mHandlerThread.getLooper());
@@ -756,7 +768,7 @@
mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
mContext = checkNotNull(context, "missing Context");
- mNetd = checkNotNull(netManager, "missing INetworkManagementService");
+ mNMS = checkNotNull(netManager, "missing INetworkManagementService");
mStatsService = checkNotNull(statsService, "missing INetworkStatsService");
mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
mPolicyManagerInternal = checkNotNull(
@@ -764,6 +776,7 @@
"missing NetworkPolicyManagerInternal");
mProxyTracker = new ProxyTracker(context, mHandler, EVENT_PROXY_HAS_CHANGED);
+ mNetd = NetdService.getInstance();
mKeyStore = KeyStore.getInstance();
mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
@@ -846,7 +859,7 @@
mTethering = makeTethering();
- mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
+ mPermissionMonitor = new PermissionMonitor(mContext, mNMS);
//set up the listener for user state for creating user VPNs
IntentFilter intentFilter = new IntentFilter();
@@ -861,8 +874,8 @@
new IntentFilter(Intent.ACTION_USER_PRESENT), null, null);
try {
- mNetd.registerObserver(mTethering);
- mNetd.registerObserver(mDataActivityObserver);
+ mNMS.registerObserver(mTethering);
+ mNMS.registerObserver(mDataActivityObserver);
} catch (RemoteException e) {
loge("Error registering observer :" + e);
}
@@ -893,7 +906,7 @@
mMultipathPolicyTracker = new MultipathPolicyTracker(mContext, mHandler);
- mDnsManager = new DnsManager(mContext, mNetd, mSystemProperties);
+ mDnsManager = new DnsManager(mContext, mNMS, mSystemProperties);
registerPrivateDnsSettingsCallbacks();
}
@@ -909,7 +922,7 @@
return mDefaultRequest;
}
};
- return new Tethering(mContext, mNetd, mStatsService, mPolicyManager,
+ return new Tethering(mContext, mNMS, mStatsService, mPolicyManager,
IoThread.get().getLooper(), new MockableSystemProperties(),
deps);
}
@@ -941,8 +954,8 @@
// 2. Give FakeSettingsProvider an alternative notification mechanism and have the test use it
// by subclassing SettingsObserver.
@VisibleForTesting
- void updateMobileDataAlwaysOn() {
- mHandler.sendEmptyMessage(EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON);
+ void updateAlwaysOnNetworks() {
+ mHandler.sendEmptyMessage(EVENT_CONFIGURE_ALWAYS_ON_NETWORKS);
}
// See FakeSettingsProvider comment above.
@@ -951,22 +964,30 @@
mHandler.sendEmptyMessage(EVENT_PRIVATE_DNS_SETTINGS_CHANGED);
}
- private void handleMobileDataAlwaysOn() {
+ private void handleAlwaysOnNetworkRequest(
+ NetworkRequest networkRequest, String settingName, boolean defaultValue) {
final boolean enable = toBool(Settings.Global.getInt(
- mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 1));
- final boolean isEnabled = (mNetworkRequests.get(mDefaultMobileDataRequest) != null);
+ mContext.getContentResolver(), settingName, encodeBool(defaultValue)));
+ final boolean isEnabled = (mNetworkRequests.get(networkRequest) != null);
if (enable == isEnabled) {
return; // Nothing to do.
}
if (enable) {
handleRegisterNetworkRequest(new NetworkRequestInfo(
- null, mDefaultMobileDataRequest, new Binder()));
+ null, networkRequest, new Binder()));
} else {
- handleReleaseNetworkRequest(mDefaultMobileDataRequest, Process.SYSTEM_UID);
+ handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID);
}
}
+ private void handleConfigureAlwaysOnNetworks() {
+ handleAlwaysOnNetworkRequest(
+ mDefaultMobileDataRequest,Settings.Global.MOBILE_DATA_ALWAYS_ON, true);
+ handleAlwaysOnNetworkRequest(mDefaultWifiRequest, Settings.Global.WIFI_ALWAYS_REQUESTED,
+ false);
+ }
+
private void registerSettingsCallbacks() {
// Watch for global HTTP proxy changes.
mSettingsObserver.observe(
@@ -976,7 +997,12 @@
// Watch for whether or not to keep mobile data always on.
mSettingsObserver.observe(
Settings.Global.getUriFor(Settings.Global.MOBILE_DATA_ALWAYS_ON),
- EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON);
+ EVENT_CONFIGURE_ALWAYS_ON_NETWORKS);
+
+ // Watch for whether or not to keep wifi always on.
+ mSettingsObserver.observe(
+ Settings.Global.getUriFor(Settings.Global.WIFI_ALWAYS_REQUESTED),
+ EVENT_CONFIGURE_ALWAYS_ON_NETWORKS);
}
private void registerPrivateDnsSettingsCallbacks() {
@@ -1473,6 +1499,20 @@
};
/**
+ * Ensures that the system cannot call a particular method.
+ */
+ private boolean disallowedBecauseSystemCaller() {
+ // TODO: start throwing a SecurityException when GnssLocationProvider stops calling
+ // requestRouteToHost.
+ if (isSystem(Binder.getCallingUid())) {
+ log("This method exists only for app backwards compatibility"
+ + " and must not be called by system services.");
+ return true;
+ }
+ return false;
+ }
+
+ /**
* Ensure that a network route exists to deliver traffic to the specified
* host via the specified network interface.
* @param networkType the type of the network over which traffic to the
@@ -1483,6 +1523,9 @@
*/
@Override
public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
+ if (disallowedBecauseSystemCaller()) {
+ return false;
+ }
enforceChangePermission();
if (mProtectedNetworks.contains(networkType)) {
enforceConnectivityInternalPermission();
@@ -1560,7 +1603,7 @@
if (DBG) log("Adding legacy route " + bestRoute +
" for UID/PID " + uid + "/" + Binder.getCallingPid());
try {
- mNetd.addLegacyRouteForNetId(netId, bestRoute, uid);
+ mNMS.addLegacyRouteForNetId(netId, bestRoute, uid);
} catch (Exception e) {
// never crash - catch them all
if (DBG) loge("Exception trying to add a route: " + e);
@@ -1680,6 +1723,11 @@
"ConnectivityService");
}
+ private boolean checkNetworkStackPermission() {
+ return PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.NETWORK_STACK);
+ }
+
private void enforceConnectivityRestrictedNetworksPermission() {
try {
mContext.enforceCallingOrSelfPermission(
@@ -1789,7 +1837,7 @@
}
void systemReady() {
- loadGlobalProxy();
+ mProxyTracker.loadGlobalProxy();
registerNetdEventCallback();
synchronized (this) {
@@ -1806,8 +1854,8 @@
// for user to unlock device too.
updateLockdownVpn();
- // Configure whether mobile data is always on.
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON));
+ // Create network requests for always-on networks.
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_CONFIGURE_ALWAYS_ON_NETWORKS));
mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_READY));
@@ -1845,7 +1893,7 @@
if (timeout > 0 && iface != null && type != ConnectivityManager.TYPE_NONE) {
try {
- mNetd.addIdleTimer(iface, timeout, type);
+ mNMS.addIdleTimer(iface, timeout, type);
} catch (Exception e) {
// You shall not crash!
loge("Exception in setupDataActivityTracking " + e);
@@ -1864,7 +1912,7 @@
caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))) {
try {
// the call fails silently if no idle timer setup for this interface
- mNetd.removeIdleTimer(iface);
+ mNMS.removeIdleTimer(iface);
} catch (Exception e) {
loge("Exception in removeDataActivityTracking " + e);
}
@@ -1872,6 +1920,18 @@
}
/**
+ * Update data activity tracking when network state is updated.
+ */
+ private void updateDataActivityTracking(NetworkAgentInfo newNetwork,
+ NetworkAgentInfo oldNetwork) {
+ if (newNetwork != null) {
+ setupDataActivityTracking(newNetwork);
+ }
+ if (oldNetwork != null) {
+ removeDataActivityTracking(oldNetwork);
+ }
+ }
+ /**
* Reads the network specific MTU size from resources.
* and set it on it's iface.
*/
@@ -1899,7 +1959,7 @@
try {
if (VDBG) log("Setting MTU size: " + iface + ", " + mtu);
- mNetd.setMtu(iface, mtu);
+ mNMS.setMtu(iface, mtu);
} catch (Exception e) {
Slog.e(TAG, "exception in setMtu()" + e);
}
@@ -2553,7 +2613,7 @@
}
nai.clearLingerState();
if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) {
- removeDataActivityTracking(nai);
+ updateDataActivityTracking(null /* newNetwork */, nai);
notifyLockdownVpn(nai);
ensureNetworkTransitionWakelock(nai.name());
}
@@ -2573,7 +2633,7 @@
// NetworkFactories, so network traffic isn't interrupted for an unnecessarily
// long time.
try {
- mNetd.removeNetwork(nai.network.netId);
+ mNMS.removeNetwork(nai.network.netId);
} catch (Exception e) {
loge("Exception removing network: " + e);
}
@@ -2771,20 +2831,6 @@
}
}
- // TODO: remove this code once we know that the Slog.wtf is never hit.
- //
- // Find all networks that are satisfying this request and remove the request
- // from their request lists.
- // TODO - it's my understanding that for a request there is only a single
- // network satisfying it, so this loop is wasteful
- for (NetworkAgentInfo otherNai : mNetworkAgentInfos.values()) {
- if (otherNai.isSatisfyingRequest(nri.request.requestId) && otherNai != nai) {
- Slog.wtf(TAG, "Request " + nri.request + " satisfied by " +
- otherNai.name() + ", but mNetworkAgentInfos says " +
- (nai != null ? nai.name() : "null"));
- }
- }
-
// Maintain the illusion. When this request arrived, we might have pretended
// that a network connected to serve it, even though the network was already
// connected. Now that this request has gone away, we might have to pretend
@@ -3098,8 +3144,8 @@
handlePromptUnvalidated((Network) msg.obj);
break;
}
- case EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON: {
- handleMobileDataAlwaysOn();
+ case EVENT_CONFIGURE_ALWAYS_ON_NETWORKS: {
+ handleConfigureAlwaysOnNetworks();
break;
}
// Sent by KeepaliveTracker to process an app request on the state machine thread.
@@ -3409,31 +3455,6 @@
mProxyTracker.setGlobalProxy(proxyProperties);
}
- private void loadGlobalProxy() {
- ContentResolver res = mContext.getContentResolver();
- String host = Settings.Global.getString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST);
- int port = Settings.Global.getInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, 0);
- String exclList = Settings.Global.getString(res,
- Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
- String pacFileUrl = Settings.Global.getString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC);
- if (!TextUtils.isEmpty(host) || !TextUtils.isEmpty(pacFileUrl)) {
- ProxyInfo proxyProperties;
- if (!TextUtils.isEmpty(pacFileUrl)) {
- proxyProperties = new ProxyInfo(pacFileUrl);
- } else {
- proxyProperties = new ProxyInfo(host, port, exclList);
- }
- if (!proxyProperties.isValid()) {
- if (DBG) log("Invalid proxy properties, ignoring: " + proxyProperties.toString());
- return;
- }
-
- synchronized (mProxyTracker.mProxyLock) {
- mProxyTracker.mGlobalProxy = proxyProperties;
- }
- }
- }
-
@Override
@Nullable
public ProxyInfo getGlobalProxy() {
@@ -3752,7 +3773,7 @@
Slog.w(TAG, "VPN for user " + user + " not ready yet. Skipping lockdown");
return false;
}
- setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, vpn, profile));
+ setLockdownTracker(new LockdownVpnTracker(mContext, mNMS, this, vpn, profile));
} else {
setLockdownTracker(null);
}
@@ -4007,7 +4028,7 @@
loge("Starting user already has a VPN");
return;
}
- userVpn = new Vpn(mHandler.getLooper(), mContext, mNetd, userId);
+ userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, userId);
mVpns.put(userId, userVpn);
if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
updateLockdownVpn();
@@ -4527,6 +4548,10 @@
// priority networks like Wi-Fi are active.
private final NetworkRequest mDefaultMobileDataRequest;
+ // Request used to optionally keep wifi data active even when higher
+ // priority networks like ethernet are active.
+ private final NetworkRequest mDefaultWifiRequest;
+
private NetworkAgentInfo getNetworkForRequest(int requestId) {
synchronized (mNetworkForRequestId) {
return mNetworkForRequestId.get(requestId);
@@ -4624,7 +4649,7 @@
mDnsManager.updatePrivateDnsStatus(netId, newLp);
// Start or stop clat accordingly to network state.
- networkAgent.updateClat(mNetd);
+ networkAgent.updateClat(mNMS);
if (isDefaultNetwork(networkAgent)) {
handleApplyDefaultProxy(newLp.getHttpProxy());
} else {
@@ -4663,9 +4688,9 @@
final String prefix = "iface:" + iface;
try {
if (add) {
- mNetd.getNetdService().wakeupAddInterface(iface, prefix, mark, mask);
+ mNetd.wakeupAddInterface(iface, prefix, mark, mask);
} else {
- mNetd.getNetdService().wakeupDelInterface(iface, prefix, mark, mask);
+ mNetd.wakeupDelInterface(iface, prefix, mark, mask);
}
} catch (Exception e) {
loge("Exception modifying wakeup packet monitoring: " + e);
@@ -4681,7 +4706,7 @@
for (String iface : interfaceDiff.added) {
try {
if (DBG) log("Adding iface " + iface + " to network " + netId);
- mNetd.addInterfaceToNetwork(iface, netId);
+ mNMS.addInterfaceToNetwork(iface, netId);
wakeupModifyInterface(iface, caps, true);
} catch (Exception e) {
loge("Exception adding interface: " + e);
@@ -4691,7 +4716,7 @@
try {
if (DBG) log("Removing iface " + iface + " from network " + netId);
wakeupModifyInterface(iface, caps, false);
- mNetd.removeInterfaceFromNetwork(iface, netId);
+ mNMS.removeInterfaceFromNetwork(iface, netId);
} catch (Exception e) {
loge("Exception removing interface: " + e);
}
@@ -4715,7 +4740,7 @@
if (route.hasGateway()) continue;
if (VDBG) log("Adding Route [" + route + "] to network " + netId);
try {
- mNetd.addRoute(netId, route);
+ mNMS.addRoute(netId, route);
} catch (Exception e) {
if ((route.getDestination().getAddress() instanceof Inet4Address) || VDBG) {
loge("Exception in addRoute for non-gateway: " + e);
@@ -4726,7 +4751,7 @@
if (route.hasGateway() == false) continue;
if (VDBG) log("Adding Route [" + route + "] to network " + netId);
try {
- mNetd.addRoute(netId, route);
+ mNMS.addRoute(netId, route);
} catch (Exception e) {
if ((route.getGateway() instanceof Inet4Address) || VDBG) {
loge("Exception in addRoute for gateway: " + e);
@@ -4737,7 +4762,7 @@
for (RouteInfo route : routeDiff.removed) {
if (VDBG) log("Removing Route [" + route + "] from network " + netId);
try {
- mNetd.removeRoute(netId, route);
+ mNMS.removeRoute(netId, route);
} catch (Exception e) {
loge("Exception in removeRoute: " + e);
}
@@ -4849,7 +4874,7 @@
final String newPermission = getNetworkPermission(newNc);
if (!Objects.equals(oldPermission, newPermission) && nai.created && !nai.isVPN()) {
try {
- mNetd.setNetworkPermission(nai.network.netId, newPermission);
+ mNMS.setNetworkPermission(nai.network.netId, newPermission);
} catch (RemoteException e) {
loge("Exception in setNetworkPermission: " + e);
}
@@ -4909,12 +4934,12 @@
if (!newRanges.isEmpty()) {
final UidRange[] addedRangesArray = new UidRange[newRanges.size()];
newRanges.toArray(addedRangesArray);
- mNetd.addVpnUidRanges(nai.network.netId, addedRangesArray);
+ mNMS.addVpnUidRanges(nai.network.netId, addedRangesArray);
}
if (!prevRanges.isEmpty()) {
final UidRange[] removedRangesArray = new UidRange[prevRanges.size()];
prevRanges.toArray(removedRangesArray);
- mNetd.removeVpnUidRanges(nai.network.netId, removedRangesArray);
+ mNMS.removeVpnUidRanges(nai.network.netId, removedRangesArray);
}
} catch (Exception e) {
// Never crash!
@@ -5083,9 +5108,9 @@
private void makeDefault(NetworkAgentInfo newNetwork) {
if (DBG) log("Switching to new default network: " + newNetwork);
- setupDataActivityTracking(newNetwork);
+
try {
- mNetd.setDefaultNetId(newNetwork.network.netId);
+ mNMS.setDefaultNetId(newNetwork.network.netId);
} catch (Exception e) {
loge("Exception setting default network :" + e);
}
@@ -5258,6 +5283,7 @@
}
}
if (isNewDefault) {
+ updateDataActivityTracking(newNetwork, oldDefaultNetwork);
// Notify system services that this network is up.
makeDefault(newNetwork);
// Log 0 -> X and Y -> X default network transitions, where X is the new default.
@@ -5480,12 +5506,12 @@
try {
// This should never fail. Specifying an already in use NetID will cause failure.
if (networkAgent.isVPN()) {
- mNetd.createVirtualNetwork(networkAgent.network.netId,
+ mNMS.createVirtualNetwork(networkAgent.network.netId,
!networkAgent.linkProperties.getDnsServers().isEmpty(),
(networkAgent.networkMisc == null ||
!networkAgent.networkMisc.allowBypass));
} else {
- mNetd.createPhysicalNetwork(networkAgent.network.netId,
+ mNMS.createPhysicalNetwork(networkAgent.network.netId,
getNetworkPermission(networkAgent.networkCapabilities));
}
} catch (Exception e) {
@@ -5922,4 +5948,49 @@
pw.println(" Get airplane mode.");
}
}
+
+ /**
+ * Caller either needs to be an active VPN, or hold the NETWORK_STACK permission
+ * for testing.
+ */
+ private Vpn enforceActiveVpnOrNetworkStackPermission() {
+ if (checkNetworkStackPermission()) {
+ return null;
+ }
+ final int uid = Binder.getCallingUid();
+ final int user = UserHandle.getUserId(uid);
+ synchronized (mVpns) {
+ Vpn vpn = mVpns.get(user);
+ try {
+ if (vpn.getVpnInfo().ownerUid == uid) return vpn;
+ } catch (NullPointerException e) {
+ /* vpn is null, or VPN is not connected and getVpnInfo() is null. */
+ }
+ }
+ throw new SecurityException("App must either be an active VPN or have the NETWORK_STACK "
+ + "permission");
+ }
+
+ /**
+ * @param connectionInfo the connection to resolve.
+ * @return {@code uid} if the connection is found and the app has permission to observe it
+ * (e.g., if it is associated with the calling VPN app's tunnel) or {@code INVALID_UID} if the
+ * connection is not found.
+ */
+ public int getConnectionOwnerUid(ConnectionInfo connectionInfo) {
+ final Vpn vpn = enforceActiveVpnOrNetworkStackPermission();
+ if (connectionInfo.protocol != IPPROTO_TCP && connectionInfo.protocol != IPPROTO_UDP) {
+ throw new IllegalArgumentException("Unsupported protocol " + connectionInfo.protocol);
+ }
+
+ final int uid = InetDiagMessage.getConnectionOwnerUid(connectionInfo.protocol,
+ connectionInfo.local, connectionInfo.remote);
+
+ /* Filter out Uids not associated with the VPN. */
+ if (vpn != null && !vpn.appliesToUid(uid)) {
+ return INVALID_UID;
+ }
+
+ return uid;
+ }
}
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 380f6a7..8c25917 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -19,6 +19,8 @@
import static android.Manifest.permission.DUMP;
import static android.net.IpSecManager.INVALID_RESOURCE_ID;
import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.AF_INET6;
+import static android.system.OsConstants.AF_UNSPEC;
import static android.system.OsConstants.EINVAL;
import static android.system.OsConstants.IPPROTO_UDP;
import static android.system.OsConstants.SOCK_DGRAM;
@@ -63,6 +65,8 @@
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
@@ -1426,6 +1430,17 @@
+ "or Encryption algorithms");
}
+ private int getFamily(String inetAddress) {
+ int family = AF_UNSPEC;
+ InetAddress checkAddress = NetworkUtils.numericToInetAddress(inetAddress);
+ if (checkAddress instanceof Inet4Address) {
+ family = AF_INET;
+ } else if (checkAddress instanceof Inet6Address) {
+ family = AF_INET6;
+ }
+ return family;
+ }
+
/**
* Checks an IpSecConfig parcel to ensure that the contents are sane and throws an
* IllegalArgumentException if they are not.
@@ -1479,6 +1494,26 @@
// Require a valid source address for all transforms.
checkInetAddress(config.getSourceAddress());
+ // Check to ensure source and destination have the same address family.
+ String sourceAddress = config.getSourceAddress();
+ String destinationAddress = config.getDestinationAddress();
+ int sourceFamily = getFamily(sourceAddress);
+ int destinationFamily = getFamily(destinationAddress);
+ if (sourceFamily != destinationFamily) {
+ throw new IllegalArgumentException(
+ "Source address ("
+ + sourceAddress
+ + ") and destination address ("
+ + destinationAddress
+ + ") have different address families.");
+ }
+
+ // Throw an error if UDP Encapsulation is not used in IPv4.
+ if (config.getEncapType() != IpSecTransform.ENCAP_NONE && sourceFamily != AF_INET) {
+ throw new IllegalArgumentException(
+ "UDP Encapsulation is not supported for this address family");
+ }
+
switch (config.getMode()) {
case IpSecTransform.MODE_TRANSPORT:
break;
@@ -1490,23 +1525,19 @@
}
}
- private static final String TUNNEL_OP = "STOPSHIP"; // = AppOpsManager.OP_MANAGE_IPSEC_TUNNELS;
+ private static final String TUNNEL_OP = AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS;
private void enforceTunnelPermissions(String callingPackage) {
checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels");
- if (false) { // STOPSHIP if this line is present
- switch (getAppOpsManager().noteOp(
- TUNNEL_OP,
- Binder.getCallingUid(), callingPackage)) {
- case AppOpsManager.MODE_DEFAULT:
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService");
- break;
- case AppOpsManager.MODE_ALLOWED:
- return;
- default:
- throw new SecurityException("Request to ignore AppOps for non-legacy API");
- }
+ switch (getAppOpsManager().noteOp(TUNNEL_OP, Binder.getCallingUid(), callingPackage)) {
+ case AppOpsManager.MODE_DEFAULT:
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService");
+ break;
+ case AppOpsManager.MODE_ALLOWED:
+ return;
+ default:
+ throw new SecurityException("Request to ignore AppOps for non-legacy API");
}
}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 9c81748..ab0a565 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -160,6 +160,8 @@
private static final int MAX_UID_RANGES_PER_COMMAND = 10;
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
/**
* Name representing {@link #setGlobalAlert(long)} limit when delivered to
* {@link INetworkManagementEventObserver#limitReached(String, String)}.
@@ -1229,18 +1231,12 @@
@Override
public void startTethering(String[] dhcpRange) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
- // cmd is "tether start first_start first_stop second_start second_stop ..."
// an odd number of addrs will fail
- final Command cmd = new Command("tether", "start");
- for (String d : dhcpRange) {
- cmd.appendArg(d);
- }
-
try {
- mConnector.execute(cmd);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ mNetdService.tetherStart(dhcpRange);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
}
}
@@ -1248,9 +1244,9 @@
public void stopTethering() {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
- mConnector.execute("tether", "stop");
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ mNetdService.tetherStop();
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
}
}
@@ -1258,25 +1254,21 @@
public boolean isTetheringStarted() {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
- final NativeDaemonEvent event;
try {
- event = mConnector.execute("tether", "status");
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ final boolean isEnabled = mNetdService.tetherIsEnabled();
+ return isEnabled;
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
}
-
- // 210 Tethering services started
- event.checkCode(TetherStatusResult);
- return event.getMessage().endsWith("started");
}
@Override
public void tetherInterface(String iface) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
- mConnector.execute("tether", "interface", "add", iface);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ mNetdService.tetherInterfaceAdd(iface);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
}
List<RouteInfo> routes = new ArrayList<>();
// The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it
@@ -1289,9 +1281,9 @@
public void untetherInterface(String iface) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
- mConnector.execute("tether", "interface", "remove", iface);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ mNetdService.tetherInterfaceRemove(iface);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
} finally {
removeInterfaceFromLocalNetwork(iface);
}
@@ -1301,11 +1293,10 @@
public String[] listTetheredInterfaces() {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
- return NativeDaemonEvent.filterMessageList(
- mConnector.executeForList("tether", "interface", "list"),
- TetherInterfaceListResult);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ final List<String> result = mNetdService.tetherInterfaceList();
+ return result.toArray(EMPTY_STRING_ARRAY);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
}
}
@@ -1314,16 +1305,11 @@
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
int netId = (network != null) ? network.netId : ConnectivityManager.NETID_UNSET;
- final Command cmd = new Command("tether", "dns", "set", netId);
-
- for (String s : dns) {
- cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress());
- }
try {
- mConnector.execute(cmd);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ mNetdService.tetherDnsSet(netId, dns);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
}
}
@@ -1331,10 +1317,10 @@
public String[] getDnsForwarders() {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
- return NativeDaemonEvent.filterMessageList(
- mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult);
- } catch (NativeDaemonConnectorException e) {
- throw e.rethrowAsParcelableException();
+ final List<String> result = mNetdService.tetherDnsList();
+ return result.toArray(EMPTY_STRING_ARRAY);
+ } catch (RemoteException | ServiceSpecificException e) {
+ throw new IllegalStateException(e);
}
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 0955bed..51c6aa1 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -50,6 +50,7 @@
import android.telephony.VoLteServiceState;
import android.util.LocalLog;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.IPhoneStateListener;
@@ -82,7 +83,8 @@
* Eventually we may want to remove the notion of dummy value but for now this
* looks like the best approach.
*/
-class TelephonyRegistry extends ITelephonyRegistry.Stub {
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public class TelephonyRegistry extends ITelephonyRegistry.Stub {
private static final String TAG = "TelephonyRegistry";
private static final boolean DBG = false; // STOPSHIP if true
private static final boolean DBG_LOC = false; // STOPSHIP if true
@@ -324,7 +326,8 @@
// calls go through a oneway interface and local calls going through a
// handler before they get to app code.
- TelephonyRegistry(Context context) {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public TelephonyRegistry(Context context) {
CellLocation location = CellLocation.getEmpty();
mContext = context;
@@ -1644,6 +1647,7 @@
intent.putExtras(data);
// Pass the subscription along with the intent.
intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+ intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
@@ -1698,6 +1702,7 @@
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
intent.setAction(PhoneConstants.ACTION_SUBSCRIPTION_PHONE_STATE_CHANGED);
intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+ intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
}
// If the phoneId is invalid, the broadcast is for overall call state.
if (phoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 59093c1..289143c 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -87,7 +87,7 @@
"media.metrics", // system/bin/mediametrics
"media.codec", // vendor/bin/hw/android.hardware.media.omx@1.0-service
"com.android.bluetooth", // Bluetooth service
- "statsd", // Stats daemon
+ "/system/bin/statsd", // Stats daemon
};
public static final List<String> HAL_INTERFACES_OF_INTEREST = Arrays.asList(
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9d0a865..6c98711 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -717,8 +717,6 @@
// Whether we should use SCHED_FIFO for UI and RenderThreads.
private boolean mUseFifoUiScheduling = false;
- private static final String SYSUI_COMPONENT_NAME = "com.android.systemui/.SystemUIService";
-
BroadcastQueue mFgBroadcastQueue;
BroadcastQueue mBgBroadcastQueue;
// Convenient for easy iteration over the queues. Foreground is first
@@ -810,7 +808,7 @@
boolean asProto) {
if (asProto) return;
doDump(fd, pw, new String[]{"activities"}, asProto);
- doDump(fd, pw, new String[]{"service", SYSUI_COMPONENT_NAME}, asProto);
+ doDump(fd, pw, new String[]{"service", "all-platform-critical"}, asProto);
}
@Override
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 0b9832d..6fa17d8 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -627,6 +627,13 @@
// If absolute volume is supported in AVRCP device
private boolean mAvrcpAbsVolSupported = false;
+ // Pre-scale for Bluetooth Absolute Volume
+ private float[] mPrescaleAbsoluteVolume = new float[] {
+ 0.5f, // Pre-scale for index 1
+ 0.7f, // Pre-scale for index 2
+ 0.85f, // Pre-scale for index 3
+ };
+
private static Long mLastDeviceConnectMsgTime = new Long(0);
private NotificationManager mNm;
@@ -878,6 +885,23 @@
mUserManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
mRecordMonitor.initMonitor();
+
+ final float[] preScale = new float[3];
+ preScale[0] = mContext.getResources().getFraction(
+ com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index1,
+ 1, 1);
+ preScale[1] = mContext.getResources().getFraction(
+ com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index2,
+ 1, 1);
+ preScale[2] = mContext.getResources().getFraction(
+ com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index3,
+ 1, 1);
+ for (int i = 0; i < preScale.length; i++) {
+ if (0.0f <= preScale[i] && preScale[i] <= 1.0f) {
+ mPrescaleAbsoluteVolume[i] = preScale[i];
+ }
+ }
+
}
public void systemReady() {
@@ -4879,18 +4903,12 @@
if (index == 0) {
// 0% for volume 0
index = 0;
- } else if (index == 1) {
- // 50% for volume 1
- index = (int)(mIndexMax * 0.5) /10;
- } else if (index == 2) {
- // 70% for volume 2
- index = (int)(mIndexMax * 0.70) /10;
- } else if (index == 3) {
- // 85% for volume 3
- index = (int)(mIndexMax * 0.85) /10;
+ } else if (index > 0 && index <= 3) {
+ // Pre-scale for volume steps 1 2 and 3
+ index = (int) (mIndexMax * mPrescaleAbsoluteVolume[index - 1]) / 10;
} else {
// otherwise, full gain
- index = (mIndexMax + 5)/10;
+ index = (mIndexMax + 5) / 10;
}
return index;
}
diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java
index dc65e1e..b7bbd42 100644
--- a/services/core/java/com/android/server/connectivity/ProxyTracker.java
+++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java
@@ -142,6 +142,35 @@
}
/**
+ * Read the global proxy settings and cache them in memory.
+ */
+ public void loadGlobalProxy() {
+ ContentResolver res = mContext.getContentResolver();
+ String host = Settings.Global.getString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST);
+ int port = Settings.Global.getInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, 0);
+ String exclList = Settings.Global.getString(res,
+ Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST);
+ String pacFileUrl = Settings.Global.getString(res, Settings.Global.GLOBAL_HTTP_PROXY_PAC);
+ if (!TextUtils.isEmpty(host) || !TextUtils.isEmpty(pacFileUrl)) {
+ ProxyInfo proxyProperties;
+ if (!TextUtils.isEmpty(pacFileUrl)) {
+ proxyProperties = new ProxyInfo(pacFileUrl);
+ } else {
+ proxyProperties = new ProxyInfo(host, port, exclList);
+ }
+ if (!proxyProperties.isValid()) {
+ if (DBG) Slog.d(TAG, "Invalid proxy properties, ignoring: " + proxyProperties);
+ return;
+ }
+
+ synchronized (mProxyLock) {
+ mGlobalProxy = proxyProperties;
+ }
+ }
+ // TODO : shouldn't this function call mPacManager.setCurrentProxyScriptUrl ?
+ }
+
+ /**
* Sends the system broadcast informing apps about a new proxy configuration.
*
* Confusingly this method also sets the PAC file URL. TODO : separate this, it has nothing
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 2a80f0e..48082b6 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -163,8 +163,8 @@
// TODO: create separate trackers for each unique VPN to support
// automated reconnection
- private Context mContext;
- private NetworkInfo mNetworkInfo;
+ private final Context mContext;
+ private final NetworkInfo mNetworkInfo;
private String mPackage;
private int mOwnerUID;
private String mInterface;
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
index 2b1d919..1e6bb04 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -320,9 +320,8 @@
}
private static boolean getEnableLegacyDhcpServer(Context ctx) {
- // TODO: make the default false (0) and update javadoc in Settings.java
final ContentResolver cr = ctx.getContentResolver();
- final int intVal = Settings.Global.getInt(cr, TETHER_ENABLE_LEGACY_DHCP_SERVER, 1);
+ final int intVal = Settings.Global.getInt(cr, TETHER_ENABLE_LEGACY_DHCP_SERVER, 0);
return intVal != 0;
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 451acf4..7745e3c 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -1879,30 +1879,36 @@
// Read partner-provided list of excluded input devices
XmlPullParser parser = null;
// Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
- File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH);
- FileReader confreader = null;
- try {
- confreader = new FileReader(confFile);
- parser = Xml.newPullParser();
- parser.setInput(confreader);
- XmlUtils.beginDocument(parser, "devices");
+ final File[] baseDirs = {
+ Environment.getRootDirectory(),
+ Environment.getVendorDirectory()
+ };
+ for (File baseDir: baseDirs) {
+ File confFile = new File(baseDir, EXCLUDED_DEVICES_PATH);
+ FileReader confreader = null;
+ try {
+ confreader = new FileReader(confFile);
+ parser = Xml.newPullParser();
+ parser.setInput(confreader);
+ XmlUtils.beginDocument(parser, "devices");
- while (true) {
- XmlUtils.nextElement(parser);
- if (!"device".equals(parser.getName())) {
- break;
+ while (true) {
+ XmlUtils.nextElement(parser);
+ if (!"device".equals(parser.getName())) {
+ break;
+ }
+ String name = parser.getAttributeValue(null, "name");
+ if (name != null) {
+ names.add(name);
+ }
}
- String name = parser.getAttributeValue(null, "name");
- if (name != null) {
- names.add(name);
- }
+ } catch (FileNotFoundException e) {
+ // It's ok if the file does not exist.
+ } catch (Exception e) {
+ Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
+ } finally {
+ try { if (confreader != null) confreader.close(); } catch (IOException e) { }
}
- } catch (FileNotFoundException e) {
- // It's ok if the file does not exist.
- } catch (Exception e) {
- Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
- } finally {
- try { if (confreader != null) confreader.close(); } catch (IOException e) { }
}
return names.toArray(new String[names.size()]);
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 60e9eaa..3f03169 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -159,8 +159,10 @@
static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE);
+ // Perform polling and persist all (FLAG_PERSIST_ALL).
private static final int MSG_PERFORM_POLL = 1;
- private static final int MSG_REGISTER_GLOBAL_ALERT = 2;
+ // Perform polling, persist network, and register the global alert again.
+ private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2;
/** Flags to control detail level of poll event. */
private static final int FLAG_PERSIST_NETWORK = 0x1;
@@ -168,6 +170,14 @@
private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
private static final int FLAG_PERSIST_FORCE = 0x100;
+ /**
+ * When global alert quota is high, wait for this delay before processing each polling,
+ * and do not schedule further polls once there is already one queued.
+ * This avoids firing the global alert too often on devices with high transfer speeds and
+ * high quota.
+ */
+ private static final int PERFORM_POLL_DELAY_MS = 1000;
+
private static final String TAG_NETSTATS_ERROR = "netstats_error";
private final Context mContext;
@@ -920,7 +930,7 @@
}
// Create baseline stats
- mHandler.sendMessage(mHandler.obtainMessage(MSG_PERFORM_POLL, FLAG_PERSIST_ALL));
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_PERFORM_POLL));
return normalizedRequest;
}
@@ -1055,13 +1065,12 @@
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
- // kick off background poll to collect network stats; UID stats
- // are handled during normal polling interval.
- final int flags = FLAG_PERSIST_NETWORK;
- mHandler.obtainMessage(MSG_PERFORM_POLL, flags, 0).sendToTarget();
-
- // re-arm global alert for next update
- mHandler.obtainMessage(MSG_REGISTER_GLOBAL_ALERT).sendToTarget();
+ // kick off background poll to collect network stats unless there is already
+ // such a call pending; UID stats are handled during normal polling interval.
+ if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) {
+ mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT,
+ PERFORM_POLL_DELAY_MS);
+ }
}
}
};
@@ -1673,11 +1682,11 @@
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_PERFORM_POLL: {
- final int flags = msg.arg1;
- mService.performPoll(flags);
+ mService.performPoll(FLAG_PERSIST_ALL);
return true;
}
- case MSG_REGISTER_GLOBAL_ALERT: {
+ case MSG_PERFORM_POLL_REGISTER_ALERT: {
+ mService.performPoll(FLAG_PERSIST_NETWORK);
mService.registerGlobalAlert();
return true;
}
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 748cf08..dea7863 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -53,16 +53,13 @@
private final static String TAG = "OTADexopt";
private final static boolean DEBUG_DEXOPT = true;
- // The synthetic library dependencies denoting "no checks."
- private final static String[] NO_LIBRARIES =
- new String[] { PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK };
-
// The amount of "available" (free - low threshold) space necessary at the start of an OTA to
// not bulk-delete unused apps' odex files.
private final static long BULK_DELETE_THRESHOLD = 1024 * 1024 * 1024; // 1GB.
private final Context mContext;
private final PackageManagerService mPackageManagerService;
+ private final MetricsLogger metricsLogger;
// TODO: Evaluate the need for WeakReferences here.
@@ -95,6 +92,7 @@
public OtaDexoptService(Context context, PackageManagerService packageManagerService) {
this.mContext = context;
this.mPackageManagerService = packageManagerService;
+ metricsLogger = new MetricsLogger();
}
public static OtaDexoptService main(Context context,
@@ -286,8 +284,8 @@
throws InstallerException {
final StringBuilder builder = new StringBuilder();
- // The current version.
- builder.append("9 ");
+ // The current version. For v10, see b/115993344.
+ builder.append("10 ");
builder.append("dexopt");
@@ -336,11 +334,6 @@
collectingInstaller, mPackageManagerService.mInstallLock, mContext);
String[] libraryDependencies = pkg.usesLibraryFiles;
- if (pkg.isSystem()) {
- // For system apps, we want to avoid classpaths checks.
- libraryDependencies = NO_LIBRARIES;
- }
-
optimizer.performDexOpt(pkg, libraryDependencies,
null /* ISAs */,
@@ -443,24 +436,22 @@
private void performMetricsLogging() {
long finalTime = System.nanoTime();
- MetricsLogger.histogram(mContext, "ota_dexopt_available_space_before_mb",
+ metricsLogger.histogram("ota_dexopt_available_space_before_mb",
inMegabytes(availableSpaceBefore));
- MetricsLogger.histogram(mContext, "ota_dexopt_available_space_after_bulk_delete_mb",
+ metricsLogger.histogram("ota_dexopt_available_space_after_bulk_delete_mb",
inMegabytes(availableSpaceAfterBulkDelete));
- MetricsLogger.histogram(mContext, "ota_dexopt_available_space_after_dexopt_mb",
+ metricsLogger.histogram("ota_dexopt_available_space_after_dexopt_mb",
inMegabytes(availableSpaceAfterDexopt));
- MetricsLogger.histogram(mContext, "ota_dexopt_num_important_packages",
- importantPackageCount);
- MetricsLogger.histogram(mContext, "ota_dexopt_num_other_packages", otherPackageCount);
+ metricsLogger.histogram("ota_dexopt_num_important_packages", importantPackageCount);
+ metricsLogger.histogram("ota_dexopt_num_other_packages", otherPackageCount);
- MetricsLogger.histogram(mContext, "ota_dexopt_num_commands", dexoptCommandCountTotal);
- MetricsLogger.histogram(mContext, "ota_dexopt_num_commands_executed",
- dexoptCommandCountExecuted);
+ metricsLogger.histogram("ota_dexopt_num_commands", dexoptCommandCountTotal);
+ metricsLogger.histogram("ota_dexopt_num_commands_executed", dexoptCommandCountExecuted);
final int elapsedTimeSeconds =
(int) TimeUnit.NANOSECONDS.toSeconds(finalTime - otaDexoptTimeStart);
- MetricsLogger.histogram(mContext, "ota_dexopt_time_s", elapsedTimeSeconds);
+ metricsLogger.histogram("ota_dexopt_time_s", elapsedTimeSeconds);
}
private static class OTADexoptPackageDexOptimizer extends
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 271d205..fae4db9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -17529,7 +17529,8 @@
// Prepare the application profiles for the new code paths.
// This needs to be done before invoking dexopt so that any install-time profile
// can be used for optimizations.
- mArtManagerService.prepareAppProfiles(pkg, resolveUserIds(args.user.getIdentifier()));
+ mArtManagerService.prepareAppProfiles(pkg, resolveUserIds(args.user.getIdentifier()),
+ /* updateReferenceProfileContent= */ true);
// Check whether we need to dexopt the app.
//
@@ -22606,8 +22607,18 @@
//
// We also have to cover non system users because we do not call the usual install package
// methods for them.
+ //
+ // NOTE: in order to speed up first boot time we only create the current profile and do not
+ // update the content of the reference profile. A system image should already be configured
+ // with the right profile keys and the profiles for the speed-profile prebuilds should
+ // already be copied. That's done in #performDexOptUpgrade.
+ //
+ // TODO(calin, mathieuc): We should use .dm files for prebuilds profiles instead of
+ // manually copying them in #performDexOptUpgrade. When we do that we should have a more
+ // granular check here and only update the existing profiles.
if (mIsUpgrade || mFirstBoot || (userId != UserHandle.USER_SYSTEM)) {
- mArtManagerService.prepareAppProfiles(pkg, userId);
+ mArtManagerService.prepareAppProfiles(pkg, userId,
+ /* updateReferenceProfileContent= */ false);
}
if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && ceDataInode != -1) {
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index 0ba7822..1fb51b7 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -16,6 +16,8 @@
package com.android.server.pm.dex;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.content.Context;
@@ -57,8 +59,6 @@
import dalvik.system.VMRuntime;
import libcore.io.IoUtils;
-import libcore.util.NonNull;
-import libcore.util.Nullable;
import java.io.File;
import java.io.FileNotFoundException;
@@ -389,7 +389,8 @@
* - create the current primary profile to save time at app startup time.
* - copy the profiles from the associated dex metadata file to the reference profile.
*/
- public void prepareAppProfiles(PackageParser.Package pkg, @UserIdInt int user) {
+ public void prepareAppProfiles(PackageParser.Package pkg, @UserIdInt int user,
+ boolean updateReferenceProfileContent) {
final int appId = UserHandle.getAppId(pkg.applicationInfo.uid);
if (user < 0) {
Slog.wtf(TAG, "Invalid user id: " + user);
@@ -404,8 +405,14 @@
for (int i = codePathsProfileNames.size() - 1; i >= 0; i--) {
String codePath = codePathsProfileNames.keyAt(i);
String profileName = codePathsProfileNames.valueAt(i);
- File dexMetadata = DexMetadataHelper.findDexMetadataForFile(new File(codePath));
- String dexMetadataPath = dexMetadata == null ? null : dexMetadata.getAbsolutePath();
+ String dexMetadataPath = null;
+ // Passing the dex metadata file to the prepare method will update the reference
+ // profile content. As such, we look for the dex metadata file only if we need to
+ // perform an update.
+ if (updateReferenceProfileContent) {
+ File dexMetadata = DexMetadataHelper.findDexMetadataForFile(new File(codePath));
+ dexMetadataPath = dexMetadata == null ? null : dexMetadata.getAbsolutePath();
+ }
synchronized (mInstaller) {
boolean result = mInstaller.prepareAppProfile(pkg.packageName, user, appId,
profileName, codePath, dexMetadataPath);
@@ -423,9 +430,10 @@
/**
* Prepares the app profiles for a set of users. {@see ArtManagerService#prepareAppProfiles}.
*/
- public void prepareAppProfiles(PackageParser.Package pkg, int[] user) {
+ public void prepareAppProfiles(PackageParser.Package pkg, int[] user,
+ boolean updateReferenceProfileContent) {
for (int i = 0; i < user.length; i++) {
- prepareAppProfiles(pkg, user[i]);
+ prepareAppProfiles(pkg, user[i], updateReferenceProfileContent);
}
}
diff --git a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
index e3e1590..602ce3b 100644
--- a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
+++ b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
@@ -93,7 +93,7 @@
@GuardedBy("mPackageUseInfoMap")
private final Map<String, PackageUseInfo> mPackageUseInfoMap;
- public PackageDexUsage() {
+ /* package */ PackageDexUsage() {
super("package-dex-usage.list", "PackageDexUsage_DiskWriter", /*lock*/ false);
mPackageUseInfoMap = new HashMap<>();
}
@@ -116,7 +116,7 @@
* @return true if the dex load constitutes new information, or false if this information
* has been seen before.
*/
- public boolean record(String owningPackageName, String dexPath, int ownerUserId,
+ /* package */ boolean record(String owningPackageName, String dexPath, int ownerUserId,
String loaderIsa, boolean isUsedByOtherApps, boolean primaryOrSplit,
String loadingPackageName, String classLoaderContext) {
if (!PackageManagerServiceUtils.checkISA(loaderIsa)) {
@@ -193,7 +193,7 @@
* Convenience method for sync reads which does not force the user to pass a useless
* (Void) null.
*/
- public void read() {
+ /* package */ void read() {
read((Void) null);
}
@@ -558,7 +558,7 @@
* Remove the usage data associated with package {@code packageName}.
* @return true if the package usage was found and removed successfully.
*/
- public boolean removePackage(String packageName) {
+ /* package */ boolean removePackage(String packageName) {
synchronized (mPackageUseInfoMap) {
return mPackageUseInfoMap.remove(packageName) != null;
}
@@ -653,11 +653,12 @@
return packages;
}
- public void clear() {
+ /* package */ void clear() {
synchronized (mPackageUseInfoMap) {
mPackageUseInfoMap.clear();
}
}
+
// Creates a deep copy of the class' mPackageUseInfoMap.
private Map<String, PackageUseInfo> clonePackageUseInfoMap() {
Map<String, PackageUseInfo> clone = new HashMap<>();
@@ -679,7 +680,7 @@
throw new IllegalArgumentException("Unknown bool encoding: " + bool);
}
- public String dump() {
+ /* package */ String dump() {
StringWriter sw = new StringWriter();
write(sw);
return sw.toString();
diff --git a/services/core/java/com/android/server/pm/dex/TEST_MAPPING b/services/core/java/com/android/server/pm/dex/TEST_MAPPING
new file mode 100644
index 0000000..ad52559
--- /dev/null
+++ b/services/core/java/com/android/server/pm/dex/TEST_MAPPING
@@ -0,0 +1,22 @@
+{
+ "presubmit": [
+ {
+ "name": "DexLoggerTests"
+ },
+ {
+ "name": "DexManagerTests"
+ },
+ {
+ "name": "DexoptOptionsTests"
+ },
+ {
+ "name": "DexoptUtilsTest"
+ },
+ {
+ "name": "PackageDexUsageTests"
+ },
+ {
+ "name": "DexLoggerIntegrationTests"
+ }
+ ]
+}
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 9aa9e47..07cdd05 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -87,7 +87,6 @@
"libsensorservicehidl",
"libgui",
"libusbhost",
- "libsuspend",
"libtinyalsa",
"libEGL",
"libGLESv2",
@@ -119,6 +118,7 @@
"android.hardware.vr@1.0",
"android.frameworks.schedulerservice@1.0",
"android.frameworks.sensorservice@1.0",
+ "android.system.suspend@1.0",
],
static_libs: [
diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
index 02ad6c7..0ff60e4 100644
--- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp
+++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
@@ -30,6 +30,8 @@
#include <android/hardware/power/1.0/IPower.h>
#include <android/hardware/power/1.1/IPower.h>
+#include <android/system/suspend/1.0/ISystemSuspend.h>
+#include <android/system/suspend/1.0/ISystemSuspendCallback.h>
#include <android_runtime/AndroidRuntime.h>
#include <jni.h>
@@ -39,7 +41,6 @@
#include <log/log.h>
#include <utils/misc.h>
#include <utils/Log.h>
-#include <suspend/autosuspend.h>
using android::hardware::Return;
using android::hardware::Void;
@@ -49,6 +50,8 @@
using android::hardware::power::V1_1::PowerStateSubsystem;
using android::hardware::power::V1_1::PowerStateSubsystemSleepState;
using android::hardware::hidl_vec;
+using android::system::suspend::V1_0::ISystemSuspend;
+using android::system::suspend::V1_0::ISystemSuspendCallback;
using IPowerV1_1 = android::hardware::power::V1_1::IPower;
using IPowerV1_0 = android::hardware::power::V1_0::IPower;
@@ -63,6 +66,7 @@
extern sp<IPowerV1_0> getPowerHalV1_0();
extern sp<IPowerV1_1> getPowerHalV1_1();
extern bool processPowerHalReturn(const Return<void> &ret, const char* functionName);
+extern sp<ISystemSuspend> getSuspendHal();
// Java methods used in getLowPowerStats
static jmethodID jgetAndUpdatePlatformState = NULL;
@@ -70,16 +74,19 @@
static jmethodID jputVoter = NULL;
static jmethodID jputState = NULL;
-static void wakeup_callback(bool success)
-{
- ALOGV("In wakeup_callback: %s", success ? "resumed from suspend" : "suspend aborted");
- int ret = sem_post(&wakeup_sem);
- if (ret < 0) {
- char buf[80];
- strerror_r(errno, buf, sizeof(buf));
- ALOGE("Error posting wakeup sem: %s\n", buf);
+class WakeupCallback : public ISystemSuspendCallback {
+public:
+ Return<void> notifyWakeup(bool success) override {
+ ALOGV("In wakeup_callback: %s", success ? "resumed from suspend" : "suspend aborted");
+ int ret = sem_post(&wakeup_sem);
+ if (ret < 0) {
+ char buf[80];
+ strerror_r(errno, buf, sizeof(buf));
+ ALOGE("Error posting wakeup sem: %s\n", buf);
+ }
+ return Void();
}
-}
+};
static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobject outBuf)
{
@@ -101,11 +108,14 @@
return -1;
}
ALOGV("Registering callback...");
- autosuspend_set_wakeup_callback(&wakeup_callback);
+ sp<ISystemSuspend> suspendHal = getSuspendHal();
+ suspendHal->registerCallback(new WakeupCallback());
}
// Wait for wakeup.
ALOGV("Waiting for wakeup...");
+ // TODO(b/116747600): device can suspend and wakeup after sem_wait() finishes and before wakeup
+ // reason is recorded, i.e. BatteryStats might occasionally miss wakeup events.
int ret = sem_wait(&wakeup_sem);
if (ret < 0) {
char buf[80];
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index b2d35d4..0c9b5f4 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -19,6 +19,7 @@
//#define LOG_NDEBUG 0
#include <android/hardware/power/1.1/IPower.h>
+#include <android/system/suspend/1.0/ISystemSuspend.h>
#include <nativehelper/JNIHelp.h>
#include "jni.h"
@@ -35,7 +36,7 @@
#include <utils/Log.h>
#include <hardware/power.h>
#include <hardware_legacy/power.h>
-#include <suspend/autosuspend.h>
+#include <hidl/ServiceManagement.h>
#include "com_android_server_power_PowerManagerService.h"
@@ -44,6 +45,9 @@
using android::hardware::power::V1_0::PowerHint;
using android::hardware::power::V1_0::Feature;
using android::String8;
+using android::system::suspend::V1_0::ISystemSuspend;
+using android::system::suspend::V1_0::IWakeLock;
+using android::system::suspend::V1_0::WakeLockType;
using IPowerV1_1 = android::hardware::power::V1_1::IPower;
using IPowerV1_0 = android::hardware::power::V1_0::IPower;
@@ -171,6 +175,46 @@
}
}
+static sp<ISystemSuspend> gSuspendHal = nullptr;
+static sp<IWakeLock> gSuspendBlocker = nullptr;
+static std::mutex gSuspendMutex;
+
+// Assume SystemSuspend HAL is always alive.
+// TODO: Force device to restart if SystemSuspend HAL dies.
+sp<ISystemSuspend> getSuspendHal() {
+ static std::once_flag suspendHalFlag;
+ std::call_once(suspendHalFlag, [](){
+ ::android::hardware::details::waitForHwService(ISystemSuspend::descriptor, "default");
+ gSuspendHal = ISystemSuspend::getService();
+ assert(gSuspendHal != nullptr);
+ });
+ return gSuspendHal;
+}
+
+void enableAutoSuspend() {
+ static bool enabled = false;
+
+ std::lock_guard<std::mutex> lock(gSuspendMutex);
+ if (!enabled) {
+ sp<ISystemSuspend> suspendHal = getSuspendHal();
+ suspendHal->enableAutosuspend();
+ enabled = true;
+ }
+ if (gSuspendBlocker) {
+ gSuspendBlocker->release();
+ gSuspendBlocker.clear();
+ }
+}
+
+void disableAutoSuspend() {
+ std::lock_guard<std::mutex> lock(gSuspendMutex);
+ if (!gSuspendBlocker) {
+ sp<ISystemSuspend> suspendHal = getSuspendHal();
+ gSuspendBlocker = suspendHal->acquireWakeLock(WakeLockType::PARTIAL,
+ "PowerManager.SuspendLockout");
+ }
+}
+
// ----------------------------------------------------------------------------
static void nativeInit(JNIEnv* env, jobject obj) {
@@ -207,13 +251,13 @@
static void nativeSetAutoSuspend(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
if (enable) {
android::base::Timer t;
- autosuspend_enable();
+ enableAutoSuspend();
if (t.duration() > 100ms) {
ALOGD("Excessive delay in autosuspend_enable() while turning screen off");
}
} else {
android::base::Timer t;
- autosuspend_disable();
+ disableAutoSuspend();
if (t.duration() > 100ms) {
ALOGD("Excessive delay in autosuspend_disable() while turning screen on");
}
diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp
index 93c4829..6c2a894 100644
--- a/services/core/jni/com_android_server_tv_TvInputHal.cpp
+++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp
@@ -390,7 +390,11 @@
[&result, &sidebandStream](Result res, const native_handle_t* handle) {
result = res;
if (res == Result::OK) {
- sidebandStream = handle;
+ if (handle) {
+ sidebandStream = native_handle_clone(handle);
+ } else {
+ result = Result::UNKNOWN;
+ }
}
});
if (result != Result::OK) {
@@ -398,7 +402,7 @@
result);
return UNKNOWN_ERROR;
}
- connection.mSourceHandle = NativeHandle::create((native_handle_t*)sidebandStream, false);
+ connection.mSourceHandle = NativeHandle::create((native_handle_t*)sidebandStream, true);
}
connection.mSurface = surface;
if (connection.mSurface != nullptr) {
diff --git a/services/devicepolicy/Android.bp b/services/devicepolicy/Android.bp
index 0505204..47790ce 100644
--- a/services/devicepolicy/Android.bp
+++ b/services/devicepolicy/Android.bp
@@ -3,7 +3,6 @@
srcs: ["java/**/*.java"],
libs: [
- "conscrypt",
"services.core",
],
}
diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
index 77a3e21..6ba7d94 100644
--- a/services/net/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -1,5 +1,8 @@
package android.net.dhcp;
+import static android.net.util.NetworkConstants.IPV4_MAX_MTU;
+import static android.net.util.NetworkConstants.IPV4_MIN_MTU;
+
import android.annotation.Nullable;
import android.net.DhcpResults;
import android.net.LinkAddress;
@@ -381,6 +384,26 @@
}
/**
+ * Returns whether a parameter is included in the parameter request list option of this packet.
+ *
+ * <p>If there is no parameter request list option in the packet, false is returned.
+ *
+ * @param paramId ID of the parameter, such as {@link #DHCP_MTU} or {@link #DHCP_HOST_NAME}.
+ */
+ public boolean hasRequestedParam(byte paramId) {
+ if (mRequestedParams == null) {
+ return false;
+ }
+
+ for (byte reqParam : mRequestedParams) {
+ if (reqParam == paramId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Creates a new L3 packet (including IP header) containing the
* DHCP udp packet. This method relies upon the delegated method
* finishPacket() to insert the per-packet contents.
@@ -696,7 +719,11 @@
addTlv(buf, DHCP_ROUTER, mGateways);
addTlv(buf, DHCP_DNS_SERVER, mDnsServers);
addTlv(buf, DHCP_DOMAIN_NAME, mDomainName);
+ addTlv(buf, DHCP_HOST_NAME, mHostName);
addTlv(buf, DHCP_VENDOR_INFO, mVendorInfo);
+ if (mMtu != null && Short.toUnsignedInt(mMtu) >= IPV4_MIN_MTU) {
+ addTlv(buf, DHCP_MTU, mMtu);
+ }
}
/**
@@ -1259,7 +1286,8 @@
boolean broadcast, Inet4Address serverIpAddr, Inet4Address relayIp,
Inet4Address yourIp, byte[] mac, Integer timeout, Inet4Address netMask,
Inet4Address bcAddr, List<Inet4Address> gateways, List<Inet4Address> dnsServers,
- Inet4Address dhcpServerIdentifier, String domainName, boolean metered) {
+ Inet4Address dhcpServerIdentifier, String domainName, String hostname, boolean metered,
+ short mtu) {
DhcpPacket pkt = new DhcpOfferPacket(
transactionId, (short) 0, broadcast, serverIpAddr, relayIp,
INADDR_ANY /* clientIp */, yourIp, mac);
@@ -1267,9 +1295,11 @@
pkt.mDnsServers = dnsServers;
pkt.mLeaseTime = timeout;
pkt.mDomainName = domainName;
+ pkt.mHostName = hostname;
pkt.mServerIdentifier = dhcpServerIdentifier;
pkt.mSubnetMask = netMask;
pkt.mBroadcastAddress = bcAddr;
+ pkt.mMtu = mtu;
if (metered) {
pkt.mVendorInfo = VENDOR_INFO_ANDROID_METERED;
}
@@ -1283,7 +1313,8 @@
boolean broadcast, Inet4Address serverIpAddr, Inet4Address relayIp, Inet4Address yourIp,
Inet4Address requestClientIp, byte[] mac, Integer timeout, Inet4Address netMask,
Inet4Address bcAddr, List<Inet4Address> gateways, List<Inet4Address> dnsServers,
- Inet4Address dhcpServerIdentifier, String domainName, boolean metered) {
+ Inet4Address dhcpServerIdentifier, String domainName, String hostname, boolean metered,
+ short mtu) {
DhcpPacket pkt = new DhcpAckPacket(
transactionId, (short) 0, broadcast, serverIpAddr, relayIp, requestClientIp, yourIp,
mac);
@@ -1291,9 +1322,11 @@
pkt.mDnsServers = dnsServers;
pkt.mLeaseTime = timeout;
pkt.mDomainName = domainName;
+ pkt.mHostName = hostname;
pkt.mSubnetMask = netMask;
pkt.mServerIdentifier = dhcpServerIdentifier;
pkt.mBroadcastAddress = bcAddr;
+ pkt.mMtu = mtu;
if (metered) {
pkt.mVendorInfo = VENDOR_INFO_ANDROID_METERED;
}
diff --git a/services/net/java/android/net/dhcp/DhcpServer.java b/services/net/java/android/net/dhcp/DhcpServer.java
index 2b3d577..cee6fa9 100644
--- a/services/net/java/android/net/dhcp/DhcpServer.java
+++ b/services/net/java/android/net/dhcp/DhcpServer.java
@@ -20,6 +20,7 @@
import static android.net.NetworkUtils.getPrefixMaskAsInet4Address;
import static android.net.TrafficStats.TAG_SYSTEM_DHCP_SERVER;
import static android.net.dhcp.DhcpPacket.DHCP_CLIENT;
+import static android.net.dhcp.DhcpPacket.DHCP_HOST_NAME;
import static android.net.dhcp.DhcpPacket.DHCP_SERVER;
import static android.net.dhcp.DhcpPacket.ENCAP_BOOTP;
import static android.net.dhcp.DhcpPacket.INFINITE_LEASE;
@@ -46,6 +47,7 @@
import android.os.SystemClock;
import android.system.ErrnoException;
import android.system.Os;
+import android.text.TextUtils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.HexDump;
@@ -350,6 +352,19 @@
return isEmpty(request.mClientIp) && (request.mBroadcast || isEmpty(lease.getNetAddr()));
}
+ /**
+ * Get the hostname from a lease if non-empty and requested in the incoming request.
+ * @param request The incoming request.
+ * @return The hostname, or null if not requested or empty.
+ */
+ @Nullable
+ private static String getHostnameIfRequested(@NonNull DhcpPacket request,
+ @NonNull DhcpLease lease) {
+ return request.hasRequestedParam(DHCP_HOST_NAME) && !TextUtils.isEmpty(lease.getHostname())
+ ? lease.getHostname()
+ : null;
+ }
+
private boolean transmitOffer(@NonNull DhcpPacket request, @NonNull DhcpLease lease,
@NonNull MacAddress clientMac) {
final boolean broadcastFlag = getBroadcastFlag(request, lease);
@@ -358,12 +373,14 @@
getPrefixMaskAsInet4Address(mServingParams.serverAddr.getPrefixLength());
final Inet4Address broadcastAddr = getBroadcastAddress(
mServingParams.getServerInet4Addr(), mServingParams.serverAddr.getPrefixLength());
+ final String hostname = getHostnameIfRequested(request, lease);
final ByteBuffer offerPacket = DhcpPacket.buildOfferPacket(
ENCAP_BOOTP, request.mTransId, broadcastFlag, mServingParams.getServerInet4Addr(),
request.mRelayIp, lease.getNetAddr(), request.mClientMac, timeout, prefixMask,
broadcastAddr, new ArrayList<>(mServingParams.defaultRouters),
new ArrayList<>(mServingParams.dnsServers),
- mServingParams.getServerInet4Addr(), null /* domainName */, mServingParams.metered);
+ mServingParams.getServerInet4Addr(), null /* domainName */, hostname,
+ mServingParams.metered, (short) mServingParams.linkMtu);
return transmitOfferOrAckPacket(offerPacket, request, lease, clientMac, broadcastFlag);
}
@@ -374,13 +391,15 @@
// transmitOffer above
final boolean broadcastFlag = getBroadcastFlag(request, lease);
final int timeout = getLeaseTimeout(lease);
+ final String hostname = getHostnameIfRequested(request, lease);
final ByteBuffer ackPacket = DhcpPacket.buildAckPacket(ENCAP_BOOTP, request.mTransId,
broadcastFlag, mServingParams.getServerInet4Addr(), request.mRelayIp,
lease.getNetAddr(), request.mClientIp, request.mClientMac, timeout,
mServingParams.getPrefixMaskAsAddress(), mServingParams.getBroadcastAddress(),
new ArrayList<>(mServingParams.defaultRouters),
new ArrayList<>(mServingParams.dnsServers),
- mServingParams.getServerInet4Addr(), null /* domainName */, mServingParams.metered);
+ mServingParams.getServerInet4Addr(), null /* domainName */, hostname,
+ mServingParams.metered, (short) mServingParams.linkMtu);
return transmitOfferOrAckPacket(ackPacket, request, lease, clientMac, broadcastFlag);
}
diff --git a/services/net/java/android/net/netlink/InetDiagMessage.java b/services/net/java/android/net/netlink/InetDiagMessage.java
new file mode 100644
index 0000000..af9e601
--- /dev/null
+++ b/services/net/java/android/net/netlink/InetDiagMessage.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 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 android.net.netlink;
+
+import static android.os.Process.INVALID_UID;
+import static android.net.netlink.NetlinkConstants.SOCK_DIAG_BY_FAMILY;
+import static android.net.netlink.NetlinkSocket.DEFAULT_RECV_BUFSIZE;
+import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
+import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
+import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.AF_INET6;
+import static android.system.OsConstants.IPPROTO_UDP;
+import static android.system.OsConstants.NETLINK_INET_DIAG;
+
+import android.os.Build;
+import android.os.Process;
+import android.system.ErrnoException;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.io.InterruptedIOException;
+import java.net.DatagramSocket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetSocketAddress;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * A NetlinkMessage subclass for netlink inet_diag messages.
+ *
+ * see also: <linux_src>/include/uapi/linux/inet_diag.h
+ *
+ * @hide
+ */
+public class InetDiagMessage extends NetlinkMessage {
+ public static final String TAG = "InetDiagMessage";
+ private static final int TIMEOUT_MS = 500;
+
+ public static byte[] InetDiagReqV2(int protocol, InetSocketAddress local,
+ InetSocketAddress remote, int family, short flags) {
+ final byte[] bytes = new byte[StructNlMsgHdr.STRUCT_SIZE + StructInetDiagReqV2.STRUCT_SIZE];
+ final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
+ byteBuffer.order(ByteOrder.nativeOrder());
+
+ final StructNlMsgHdr nlMsgHdr = new StructNlMsgHdr();
+ nlMsgHdr.nlmsg_len = bytes.length;
+ nlMsgHdr.nlmsg_type = SOCK_DIAG_BY_FAMILY;
+ nlMsgHdr.nlmsg_flags = flags;
+ nlMsgHdr.pack(byteBuffer);
+
+ final StructInetDiagReqV2 inetDiagReqV2 = new StructInetDiagReqV2(protocol, local, remote,
+ family);
+ inetDiagReqV2.pack(byteBuffer);
+ return bytes;
+ }
+
+ public StructInetDiagMsg mStructInetDiagMsg;
+
+ private InetDiagMessage(StructNlMsgHdr header) {
+ super(header);
+ mStructInetDiagMsg = new StructInetDiagMsg();
+ }
+
+ public static InetDiagMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) {
+ final InetDiagMessage msg = new InetDiagMessage(header);
+ msg.mStructInetDiagMsg = StructInetDiagMsg.parse(byteBuffer);
+ return msg;
+ }
+
+ private static int lookupUidByFamily(int protocol, InetSocketAddress local,
+ InetSocketAddress remote, int family, short flags,
+ FileDescriptor fd)
+ throws ErrnoException, InterruptedIOException {
+ byte[] msg = InetDiagReqV2(protocol, local, remote, family, flags);
+ NetlinkSocket.sendMessage(fd, msg, 0, msg.length, TIMEOUT_MS);
+ ByteBuffer response = NetlinkSocket.recvMessage(fd, DEFAULT_RECV_BUFSIZE, TIMEOUT_MS);
+
+ final NetlinkMessage nlMsg = NetlinkMessage.parse(response);
+ final StructNlMsgHdr hdr = nlMsg.getHeader();
+ if (hdr.nlmsg_type == NetlinkConstants.NLMSG_DONE) {
+ return INVALID_UID;
+ }
+ if (nlMsg instanceof InetDiagMessage) {
+ return ((InetDiagMessage) nlMsg).mStructInetDiagMsg.idiag_uid;
+ }
+ return INVALID_UID;
+ }
+
+ private static final int FAMILY[] = {AF_INET6, AF_INET};
+
+ private static int lookupUid(int protocol, InetSocketAddress local,
+ InetSocketAddress remote, FileDescriptor fd)
+ throws ErrnoException, InterruptedIOException {
+ int uid;
+
+ for (int family : FAMILY) {
+ /**
+ * For exact match lookup, swap local and remote for UDP lookups due to kernel
+ * bug which will not be fixed. See aosp/755889 and
+ * https://www.mail-archive.com/netdev@vger.kernel.org/msg248638.html
+ */
+ if (protocol == IPPROTO_UDP) {
+ uid = lookupUidByFamily(protocol, remote, local, family, NLM_F_REQUEST, fd);
+ } else {
+ uid = lookupUidByFamily(protocol, local, remote, family, NLM_F_REQUEST, fd);
+ }
+ if (uid != INVALID_UID) {
+ return uid;
+ }
+ }
+
+ /**
+ * For UDP it's possible for a socket to send packets to arbitrary destinations, even if the
+ * socket is not connected (and even if the socket is connected to a different destination).
+ * If we want this API to work for such packets, then on miss we need to do a second lookup
+ * with only the local address and port filled in.
+ * Always use flags == NLM_F_REQUEST | NLM_F_DUMP for wildcard.
+ */
+ if (protocol == IPPROTO_UDP) {
+ try {
+ InetSocketAddress wildcard = new InetSocketAddress(
+ Inet6Address.getByName("::"), 0);
+ uid = lookupUidByFamily(protocol, local, wildcard, AF_INET6,
+ (short) (NLM_F_REQUEST | NLM_F_DUMP), fd);
+ if (uid != INVALID_UID) {
+ return uid;
+ }
+ wildcard = new InetSocketAddress(Inet4Address.getByName("0.0.0.0"), 0);
+ uid = lookupUidByFamily(protocol, local, wildcard, AF_INET,
+ (short) (NLM_F_REQUEST | NLM_F_DUMP), fd);
+ if (uid != INVALID_UID) {
+ return uid;
+ }
+ } catch (UnknownHostException e) {
+ Log.e(TAG, e.toString());
+ }
+ }
+ return INVALID_UID;
+ }
+
+ /**
+ * Use an inet_diag socket to look up the UID associated with the input local and remote
+ * address/port and protocol of a connection.
+ */
+ public static int getConnectionOwnerUid(int protocol, InetSocketAddress local,
+ InetSocketAddress remote) {
+ try {
+ final FileDescriptor fd = NetlinkSocket.forProto(NETLINK_INET_DIAG);
+ NetlinkSocket.connectToKernel(fd);
+
+ return lookupUid(protocol, local, remote, fd);
+
+ } catch (ErrnoException | SocketException | IllegalArgumentException
+ | InterruptedIOException e) {
+ Log.e(TAG, e.toString());
+ }
+ return INVALID_UID;
+ }
+
+ @Override
+ public String toString() {
+ return "InetDiagMessage{ "
+ + "nlmsghdr{" + (mHeader == null ? "" : mHeader.toString()) + "}, "
+ + "inet_diag_msg{"
+ + (mStructInetDiagMsg == null ? "" : mStructInetDiagMsg.toString()) + "} "
+ + "}";
+ }
+}
diff --git a/services/net/java/android/net/netlink/NetlinkConstants.java b/services/net/java/android/net/netlink/NetlinkConstants.java
index e331701..fc1551c 100644
--- a/services/net/java/android/net/netlink/NetlinkConstants.java
+++ b/services/net/java/android/net/netlink/NetlinkConstants.java
@@ -54,6 +54,12 @@
return String.valueOf(family);
}
+ public static String stringForProtocol(int protocol) {
+ if (protocol == OsConstants.IPPROTO_TCP) { return "IPPROTO_TCP"; }
+ if (protocol == OsConstants.IPPROTO_UDP) { return "IPPROTO_UDP"; }
+ return String.valueOf(protocol);
+ }
+
public static String hexify(byte[] bytes) {
if (bytes == null) { return "(null)"; }
return HexDump.toHexString(bytes);
@@ -90,6 +96,9 @@
public static final short RTM_GETRULE = 34;
public static final short RTM_NEWNDUSEROPT = 68;
+ /* see <linux_src>/include/uapi/linux/sock_diag.h */
+ public static final short SOCK_DIAG_BY_FAMILY = 20;
+
public static String stringForNlMsgType(short nlm_type) {
switch (nlm_type) {
case NLMSG_NOOP: return "NLMSG_NOOP";
diff --git a/services/net/java/android/net/netlink/NetlinkMessage.java b/services/net/java/android/net/netlink/NetlinkMessage.java
index 3bf75ca..a325db8 100644
--- a/services/net/java/android/net/netlink/NetlinkMessage.java
+++ b/services/net/java/android/net/netlink/NetlinkMessage.java
@@ -69,6 +69,8 @@
case NetlinkConstants.RTM_DELNEIGH:
case NetlinkConstants.RTM_GETNEIGH:
return (NetlinkMessage) RtNetlinkNeighborMessage.parse(nlmsghdr, byteBuffer);
+ case NetlinkConstants.SOCK_DIAG_BY_FAMILY:
+ return (NetlinkMessage) InetDiagMessage.parse(nlmsghdr, byteBuffer);
default:
if (nlmsghdr.nlmsg_type <= NetlinkConstants.NLMSG_MAX_RESERVED) {
// Netlink control message. Just parse the header for now,
diff --git a/services/net/java/android/net/netlink/StructInetDiagMsg.java b/services/net/java/android/net/netlink/StructInetDiagMsg.java
new file mode 100644
index 0000000..da824ad
--- /dev/null
+++ b/services/net/java/android/net/netlink/StructInetDiagMsg.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 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 android.net.netlink;
+
+import static java.nio.ByteOrder.BIG_ENDIAN;
+import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.AF_INET6;
+
+import java.net.Inet4Address;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import android.util.Log;
+
+/**
+ * struct inet_diag_msg
+ *
+ * see <linux_src>/include/uapi/linux/inet_diag.h
+ *
+ * struct inet_diag_msg {
+ * __u8 idiag_family;
+ * __u8 idiag_state;
+ * __u8 idiag_timer;
+ * __u8 idiag_retrans;
+ * struct inet_diag_sockid id;
+ * __u32 idiag_expires;
+ * __u32 idiag_rqueue;
+ * __u32 idiag_wqueue;
+ * __u32 idiag_uid;
+ * __u32 idiag_inode;
+ * };
+ *
+ * @hide
+ */
+public class StructInetDiagMsg {
+ public static final int STRUCT_SIZE = 4 + StructInetDiagSockId.STRUCT_SIZE + 20;
+ private static final int IDIAG_UID_OFFSET = StructNlMsgHdr.STRUCT_SIZE + 4 +
+ StructInetDiagSockId.STRUCT_SIZE + 12;
+ public int idiag_uid;
+
+ public static StructInetDiagMsg parse(ByteBuffer byteBuffer) {
+ StructInetDiagMsg struct = new StructInetDiagMsg();
+ struct.idiag_uid = byteBuffer.getInt(IDIAG_UID_OFFSET);
+ return struct;
+ }
+
+ @Override
+ public String toString() {
+ return "StructInetDiagMsg{ "
+ + "idiag_uid{" + idiag_uid + "}, "
+ + "}";
+ }
+}
diff --git a/services/net/java/android/net/netlink/StructInetDiagReqV2.java b/services/net/java/android/net/netlink/StructInetDiagReqV2.java
new file mode 100644
index 0000000..49a9325
--- /dev/null
+++ b/services/net/java/android/net/netlink/StructInetDiagReqV2.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 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 android.net.netlink;
+
+import static java.nio.ByteOrder.BIG_ENDIAN;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * struct inet_diag_req_v2
+ *
+ * see <linux_src>/include/uapi/linux/inet_diag.h
+ *
+ * struct inet_diag_req_v2 {
+ * __u8 sdiag_family;
+ * __u8 sdiag_protocol;
+ * __u8 idiag_ext;
+ * __u8 pad;
+ * __u32 idiag_states;
+ * struct inet_diag_sockid id;
+ * };
+ *
+ * @hide
+ */
+public class StructInetDiagReqV2 {
+ public static final int STRUCT_SIZE = 8 + StructInetDiagSockId.STRUCT_SIZE;
+
+ private final byte sdiag_family;
+ private final byte sdiag_protocol;
+ private final StructInetDiagSockId id;
+ private final int INET_DIAG_REQ_V2_ALL_STATES = (int) 0xffffffff;
+
+
+ public StructInetDiagReqV2(int protocol, InetSocketAddress local, InetSocketAddress remote,
+ int family) {
+ sdiag_family = (byte) family;
+ sdiag_protocol = (byte) protocol;
+ id = new StructInetDiagSockId(local, remote);
+ }
+
+ public void pack(ByteBuffer byteBuffer) {
+ // The ByteOrder must have already been set by the caller.
+ byteBuffer.put((byte) sdiag_family);
+ byteBuffer.put((byte) sdiag_protocol);
+ byteBuffer.put((byte) 0);
+ byteBuffer.put((byte) 0);
+ byteBuffer.putInt(INET_DIAG_REQ_V2_ALL_STATES);
+ id.pack(byteBuffer);
+ }
+
+ @Override
+ public String toString() {
+ final String familyStr = NetlinkConstants.stringForAddressFamily(sdiag_family);
+ final String protocolStr = NetlinkConstants.stringForAddressFamily(sdiag_protocol);
+
+ return "StructInetDiagReqV2{ "
+ + "sdiag_family{" + familyStr + "}, "
+ + "sdiag_protocol{" + protocolStr + "}, "
+ + "idiag_ext{" + 0 + ")}, "
+ + "pad{" + 0 + "}, "
+ + "idiag_states{" + Integer.toHexString(INET_DIAG_REQ_V2_ALL_STATES) + "}, "
+ + id.toString()
+ + "}";
+ }
+}
diff --git a/services/net/java/android/net/netlink/StructInetDiagSockId.java b/services/net/java/android/net/netlink/StructInetDiagSockId.java
new file mode 100644
index 0000000..2e9fa25
--- /dev/null
+++ b/services/net/java/android/net/netlink/StructInetDiagSockId.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 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 android.net.netlink;
+
+import static java.nio.ByteOrder.BIG_ENDIAN;
+
+import java.net.Inet4Address;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * struct inet_diag_req_v2
+ *
+ * see <linux_src>/include/uapi/linux/inet_diag.h
+ *
+ * struct inet_diag_sockid {
+ * __be16 idiag_sport;
+ * __be16 idiag_dport;
+ * __be32 idiag_src[4];
+ * __be32 idiag_dst[4];
+ * __u32 idiag_if;
+ * __u32 idiag_cookie[2];
+ * #define INET_DIAG_NOCOOKIE (~0U)
+ * };
+ *
+ * @hide
+ */
+public class StructInetDiagSockId {
+ public static final int STRUCT_SIZE = 48;
+
+ private final InetSocketAddress mLocSocketAddress;
+ private final InetSocketAddress mRemSocketAddress;
+ private final byte[] INET_DIAG_NOCOOKIE = new byte[]{
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
+ private final byte[] IPV4_PADDING = new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ public StructInetDiagSockId(InetSocketAddress loc, InetSocketAddress rem) {
+ mLocSocketAddress = loc;
+ mRemSocketAddress = rem;
+ }
+
+ public void pack(ByteBuffer byteBuffer) {
+ byteBuffer.order(BIG_ENDIAN);
+ byteBuffer.putShort((short) mLocSocketAddress.getPort());
+ byteBuffer.putShort((short) mRemSocketAddress.getPort());
+ byteBuffer.put(mLocSocketAddress.getAddress().getAddress());
+ if (mLocSocketAddress.getAddress() instanceof Inet4Address) {
+ byteBuffer.put(IPV4_PADDING);
+ }
+ byteBuffer.put(mRemSocketAddress.getAddress().getAddress());
+ if (mRemSocketAddress.getAddress() instanceof Inet4Address) {
+ byteBuffer.put(IPV4_PADDING);
+ }
+ byteBuffer.order(ByteOrder.nativeOrder());
+ byteBuffer.putInt(0);
+ byteBuffer.put(INET_DIAG_NOCOOKIE);
+ }
+
+ @Override
+ public String toString() {
+ return "StructInetDiagSockId{ "
+ + "idiag_sport{" + mLocSocketAddress.getPort() + "}, "
+ + "idiag_dport{" + mRemSocketAddress.getPort() + "}, "
+ + "idiag_src{" + mLocSocketAddress.getAddress().getHostAddress() + "}, "
+ + "idiag_dst{" + mRemSocketAddress.getAddress().getHostAddress() + "}, "
+ + "idiag_if{" + 0 + "} "
+ + "idiag_cookie{INET_DIAG_NOCOOKIE}"
+ + "}";
+ }
+}
diff --git a/services/net/java/android/net/util/SharedLog.java b/services/net/java/android/net/util/SharedLog.java
index f7bf393..5a73a4e 100644
--- a/services/net/java/android/net/util/SharedLog.java
+++ b/services/net/java/android/net/util/SharedLog.java
@@ -17,6 +17,7 @@
package android.net.util;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.text.TextUtils;
import android.util.LocalLog;
import android.util.Log;
@@ -92,10 +93,17 @@
}
/**
- * Log an error due to an exception, with the exception stacktrace.
+ * Log an error due to an exception, with the exception stacktrace if provided.
+ *
+ * <p>The error and exception message appear in the shared log, but the stacktrace is only
+ * logged in general log output (logcat).
*/
- public void e(@NonNull String msg, @NonNull Throwable e) {
- Log.e(mTag, record(Category.ERROR, msg + ": " + e.getMessage()), e);
+ public void e(@NonNull String msg, @Nullable Throwable exception) {
+ if (exception == null) {
+ e(msg);
+ return;
+ }
+ Log.e(mTag, record(Category.ERROR, msg + ": " + exception.getMessage()), exception);
}
public void i(String msg) {
diff --git a/services/tests/runtests.py b/services/tests/runtests.py
index 7980dc2..f19cc5d 100755
--- a/services/tests/runtests.py
+++ b/services/tests/runtests.py
@@ -22,8 +22,7 @@
'android.support.test.runner.AndroidJUnitRunner')
PACKAGE_WHITELIST = (
- 'android.net',
- 'com.android.server.connectivity',
+ "com.android.server",
)
COLOR_RED = '\033[0;31m'
@@ -37,14 +36,27 @@
COLOR_NONE)
return subprocess.check_call(shell_command, shell=True)
-
+# usage:
+# ${ANDROID_BUILD_TOP}/frameworks/base/services/tests/runtests.py : run tests in com.android.server
+# ${ANDROID_BUILD_TOP}/frameworks/base/services/tests/runtests.py -e package [package name, e.g. com.android.server]
+# ${ANDROID_BUILD_TOP}/frameworks/base/services/tests/runtests.py -e class [class name, e.g. com.android.server.MountServiceTests]
+#
+# The available INSTRUMENTED_PACKAGE_RUNNER may differ in different environments.
+# In this case, use "adb shell pm list instrumentation" to query available runners
+# and use the environment variable INSTRUMENTED_PACKAGE_RUNNER to overwrite
+# the default one, e.g.,
+# INSTRUMENTED_PACKAGE_RUNNER=com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner \
+# ${ANDROID_BUILD_TOP}/frameworks/base/services/tests/runtests.py
+#
def main():
build_top = os.environ.get('ANDROID_BUILD_TOP', None)
out_dir = os.environ.get('OUT', None)
+ runner = os.environ.get('INSTRUMENTED_PACKAGE_RUNNER', None)
if build_top is None or out_dir is None:
print 'You need to source and lunch before you can use this script'
return 1
-
+ if runner is None:
+ runner = INSTRUMENTED_PACKAGE_RUNNER
print 'Building tests...'
run('make -j32 -C %s -f build/core/main.mk '
'MODULES-IN-frameworks-base-services-tests-servicestests' % build_top,
@@ -57,19 +69,19 @@
apk_path = (
'%s/data/app/FrameworksServicesTests/FrameworksServicesTests.apk' %
out_dir)
- run('adb install -r -g "%s"' % apk_path)
+ run('adb install -t -r -g "%s"' % apk_path)
print 'Running tests...'
if len(sys.argv) != 1:
run('adb shell am instrument -w %s "%s"' %
- (' '.join(sys.argv[1:]), INSTRUMENTED_PACKAGE_RUNNER))
+ (' '.join(sys.argv[1:]), runner))
return 0
# It would be nice if the activity manager accepted a list of packages, but
# in lieu of that...
for package in PACKAGE_WHITELIST:
run('adb shell am instrument -w -e package %s %s' %
- (package, INSTRUMENTED_PACKAGE_RUNNER))
+ (package, runner))
return 0
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index a85f21c..00ebae6 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -9,7 +9,9 @@
LOCAL_MODULE_TAGS := tests
# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, src) \
+ $(call all-java-files-under, utils) \
LOCAL_STATIC_JAVA_LIBRARIES := \
frameworks-base-testutils \
@@ -55,6 +57,7 @@
libbacktrace \
libbase \
libbinder \
+ libbinderthreadstate \
libc++ \
libcutils \
liblog \
diff --git a/services/tests/servicestests/src/com/android/server/testutils/OffsettableClock.java b/services/tests/servicestests/utils/com/android/server/testutils/OffsettableClock.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/testutils/OffsettableClock.java
rename to services/tests/servicestests/utils/com/android/server/testutils/OffsettableClock.java
diff --git a/services/tests/servicestests/src/com/android/server/testutils/TestHandler.java b/services/tests/servicestests/utils/com/android/server/testutils/TestHandler.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/testutils/TestHandler.java
rename to services/tests/servicestests/utils/com/android/server/testutils/TestHandler.java
diff --git a/services/tests/servicestests/src/com/android/server/testutils/TestUtils.java b/services/tests/servicestests/utils/com/android/server/testutils/TestUtils.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/testutils/TestUtils.java
rename to services/tests/servicestests/utils/com/android/server/testutils/TestUtils.java
diff --git a/services/tests/uiservicestests/Android.mk b/services/tests/uiservicestests/Android.mk
index b98bc89..3fa776c 100644
--- a/services/tests/uiservicestests/Android.mk
+++ b/services/tests/uiservicestests/Android.mk
@@ -45,6 +45,7 @@
libbacktrace \
libbase \
libbinder \
+ libbinderthreadstate \
libc++ \
libcutils \
liblog \
diff --git a/services/tests/wmtests/Android.mk b/services/tests/wmtests/Android.mk
new file mode 100644
index 0000000..cd28974
--- /dev/null
+++ b/services/tests/wmtests/Android.mk
@@ -0,0 +1,46 @@
+#########################################################################
+# Build WmTests package
+#########################################################################
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files.
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, src) \
+ $(call all-java-files-under, ../servicestests/utils)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ frameworks-base-testutils \
+ services.core \
+ android-support-test \
+ mockito-target-minus-junit4 \
+ platform-test-annotations \
+ truth-prebuilt \
+ testables \
+ ub-uiautomator \
+
+LOCAL_JAVA_LIBRARIES := \
+ android.test.mock \
+ android.test.base \
+ android.test.runner \
+
+LOCAL_PACKAGE_NAME := WmTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_COMPATIBILITY_SUITE := device-tests
+
+LOCAL_CERTIFICATE := platform
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_JACK_FLAGS := --multi-dex native
+LOCAL_DX_FLAGS := --multi-dex
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
new file mode 100644
index 0000000..7e4bd42
--- /dev/null
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.wmtests">
+
+ <!-- Uses API introduced in P (28) -->
+ <uses-sdk
+ android:minSdkVersion="1"
+ android:targetSdkVersion="28" />
+
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+ <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
+ <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+ <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
+ <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
+ <uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
+ <uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO" />
+ <uses-permission android:name="android.permission.REORDER_TASKS" />
+ <uses-permission android:name="android.permission.MANAGE_USERS" />
+
+ <application android:testOnly="true">
+ <activity android:name="com.android.server.am.TaskStackChangedListenerTest$ActivityA" />
+ <activity android:name="com.android.server.am.TaskStackChangedListenerTest$ActivityB" />
+ <activity android:name="com.android.server.am.TaskStackChangedListenerTest$ActivityRequestedOrientationChange" />
+ <activity android:name="com.android.server.am.TaskStackChangedListenerTest$ActivityTaskChangeCallbacks" />
+ <activity android:name="com.android.server.am.TaskStackChangedListenerTest$ActivityTaskDescriptionChange" />
+ <activity android:name="com.android.server.wm.ScreenDecorWindowTests$TestActivity" />
+ </application>
+
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:label="Window Manager Tests"
+ android:targetPackage="com.android.frameworks.wmtests" />
+</manifest>
diff --git a/services/tests/wmtests/AndroidTest.xml b/services/tests/wmtests/AndroidTest.xml
new file mode 100644
index 0000000..38a62ae
--- /dev/null
+++ b/services/tests/wmtests/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 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.
+-->
+
+<configuration description="Runs Window Manager Tests.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="install-arg" value="-t" />
+ <option name="test-file-name" value="WmTests.apk" />
+ </target_preparer>
+
+ <option name="test-tag" value="WmTests" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.frameworks.wmtests" />
+ <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
similarity index 97%
rename from services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
rename to services/tests/wmtests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
index f741c70..089dc61 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/am/ActivityLaunchParamsModifierTests.java
@@ -16,6 +16,16 @@
package com.android.server.am;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
import android.app.ActivityOptions;
import android.content.pm.ActivityInfo;
import android.graphics.Rect;
@@ -24,26 +34,16 @@
import android.support.test.runner.AndroidJUnit4;
import com.android.server.am.LaunchParamsController.LaunchParams;
-import org.junit.runner.RunWith;
+
import org.junit.Before;
import org.junit.Test;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.doAnswer;
-
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
+import org.junit.runner.RunWith;
/**
* Tests for exercising resizing bounds due to activity options.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:ActivityLaunchParamsModifierTests
+ * atest WmTests:ActivityLaunchParamsModifierTests
*/
@MediumTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java b/services/tests/wmtests/src/com/android/server/am/ActivityManagerInternalTest.java
similarity index 93%
rename from services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java
rename to services/tests/wmtests/src/com/android/server/am/ActivityManagerInternalTest.java
index bce87dc..f393d14 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/ActivityManagerInternalTest.java
@@ -33,17 +33,8 @@
/**
* Test class for {@link ActivityManagerInternal}.
*
- * To run the tests, use
- *
- * runtest -c com.android.server.am.ActivityManagerInternalTest frameworks-services
- *
- * or the following steps:
- *
- * Build: m FrameworksServicesTests
- * Install: adb install -r \
- * ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
- * Run: adb shell am instrument -e class com.android.server.am.ActivityManagerInternalTest -w \
- * com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ * Build/Install/Run:
+ * atest WmTests:ActivityManagerInternalTest
*/
@RunWith(AndroidJUnit4.class)
public class ActivityManagerInternalTest {
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/wmtests/src/com/android/server/am/ActivityManagerServiceTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
rename to services/tests/wmtests/src/com/android/server/am/ActivityManagerServiceTest.java
index c70d1e1..c41197d 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -28,6 +28,7 @@
import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.util.DebugUtils.valueToString;
+
import static com.android.server.am.ActivityManagerInternalTest.CustomThread;
import static com.android.server.am.ActivityManagerService.DISPATCH_UIDS_CHANGED_UI_MSG;
import static com.android.server.am.ActivityManagerService.Injector;
@@ -88,17 +89,8 @@
/**
* Test class for {@link ActivityManagerService}.
*
- * To run the tests, use
- *
- * runtest -c com.android.server.am.ActivityManagerServiceTest frameworks-services
- *
- * or the following steps:
- *
- * Build: m FrameworksServicesTests
- * Install: adb install -r \
- * ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
- * Run: adb shell am instrument -e class com.android.server.am.ActivityManagerServiceTest -w \
- * com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ * Build/Install/Run:
+ * atest WmTests:ActivityManagerServiceTest
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -830,4 +822,4 @@
mRestricted = restricted;
}
}
-}
\ No newline at end of file
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java b/services/tests/wmtests/src/com/android/server/am/ActivityManagerTest.java
similarity index 94%
rename from services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java
rename to services/tests/wmtests/src/com/android/server/am/ActivityManagerTest.java
index ba25b16..a2f942e 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/ActivityManagerTest.java
@@ -18,13 +18,18 @@
import android.app.ActivityManager;
import android.app.IActivityManager;
-import android.os.ServiceManager;
-import android.os.UserHandle;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.test.AndroidTestCase;
import java.util.List;
+/**
+ * Tests for {@link ActivityManager}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:ActivityManagerTest
+ */
public class ActivityManagerTest extends AndroidTestCase {
IActivityManager service;
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/am/ActivityRecordTests.java
similarity index 96%
rename from services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
rename to services/tests/wmtests/src/com/android/server/am/ActivityRecordTests.java
index 5ee1c40..616cc0f 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/am/ActivityRecordTests.java
@@ -22,11 +22,7 @@
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
-import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
-import static com.android.server.am.ActivityStack.ActivityState.FINISHING;
import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING;
-import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
@@ -57,17 +53,16 @@
import android.support.test.runner.AndroidJUnit4;
import android.util.MutableBoolean;
-import org.junit.runner.RunWith;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.invocation.InvocationOnMock;
/**
* Tests for the {@link ActivityRecord} class.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:com.android.server.am.ActivityRecordTests
+ * atest WmTests:com.android.server.am.ActivityRecordTests
*/
@MediumTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/am/ActivityStackSupervisorTests.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
rename to services/tests/wmtests/src/com/android/server/am/ActivityStackSupervisorTests.java
index 1ce41a6..2209b66 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -62,7 +62,7 @@
* Tests for the {@link ActivityStackSupervisor} class.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:com.android.server.am.ActivityStackSupervisorTests
+ * atest WmTests:ActivityStackSupervisorTests
*/
@MediumTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/am/ActivityStackTests.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
rename to services/tests/wmtests/src/com/android/server/am/ActivityStackTests.java
index 01425ed..cac264b 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/am/ActivityStackTests.java
@@ -33,13 +33,9 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
import android.content.pm.ActivityInfo;
import android.os.UserHandle;
@@ -47,15 +43,15 @@
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import org.junit.runner.RunWith;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Tests for the {@link ActivityStack} class.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:com.android.server.am.ActivityStackTests
+ * atest WmTests:ActivityStackTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java b/services/tests/wmtests/src/com/android/server/am/ActivityStartControllerTests.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
rename to services/tests/wmtests/src/com/android/server/am/ActivityStartControllerTests.java
index 7948e4c..37a5a17 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/am/ActivityStartControllerTests.java
@@ -19,6 +19,13 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
import android.content.Intent;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
@@ -27,15 +34,8 @@
import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
import com.android.server.am.ActivityStarter.Factory;
-import org.junit.runner.RunWith;
import org.junit.Test;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.times;
+import org.junit.runner.RunWith;
import java.util.Random;
@@ -43,7 +43,7 @@
* Tests for the {@link ActivityStartController} class.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:ActivityStartControllerTests
+ * atest WmTests:ActivityStartControllerTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/am/ActivityStartInterceptorTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
rename to services/tests/wmtests/src/com/android/server/am/ActivityStartInterceptorTest.java
index b4b34c5..8f2d284 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/ActivityStartInterceptorTest.java
@@ -55,7 +55,7 @@
* Unit tests for {@link ActivityStartInterceptorTest}.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.am.ActivityStartInterceptorTest
+ * bit WmTests:ActivityStartInterceptorTest
*/
@SmallTest
public class ActivityStartInterceptorTest {
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/am/ActivityStarterTests.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
rename to services/tests/wmtests/src/com/android/server/am/ActivityStarterTests.java
index 1520859..048df43 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/am/ActivityStarterTests.java
@@ -32,10 +32,26 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
+
+import static com.android.server.am.ActivityManagerService.ANIMATE;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyObject;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import android.app.ActivityOptions;
import android.app.IApplicationThread;
-import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.WindowLayout;
@@ -50,39 +66,18 @@
import android.support.test.runner.AndroidJUnit4;
import android.view.Gravity;
-import org.junit.runner.RunWith;
-import org.junit.Test;
-
-import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
-import static com.android.server.am.ActivityManagerService.ANIMATE;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyBoolean;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyObject;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.times;
-
import com.android.internal.os.BatteryStatsImpl;
-import com.android.server.am.ActivityStarter.Factory;
import com.android.server.am.LaunchParamsController.LaunchParamsModifier;
import com.android.server.am.TaskRecord.TaskRecordFactory;
-import java.util.ArrayList;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Tests for the {@link ActivityStarter} class.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:ActivityStarterTests
+ * atest WmTests:ActivityStarterTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/am/ActivityTestsBase.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
rename to services/tests/wmtests/src/com/android/server/am/ActivityTestsBase.java
index 1cd111f..d9a346b 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/am/ActivityTestsBase.java
@@ -21,21 +21,17 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.view.Display.DEFAULT_DISPLAY;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
+
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import android.app.ActivityOptions;
-import com.android.server.wm.DisplayWindowController;
-
-import org.junit.Rule;
-import org.mockito.invocation.InvocationOnMock;
-
import android.app.IApplicationThread;
import android.content.ComponentName;
import android.content.Context;
@@ -52,20 +48,21 @@
import android.support.test.InstrumentationRegistry;
import android.testing.DexmakerShareClassLoaderRule;
-
import com.android.internal.app.IVoiceInteractor;
-
import com.android.server.AttributeCache;
import com.android.server.wm.AppWindowContainerController;
+import com.android.server.wm.DisplayWindowController;
import com.android.server.wm.PinnedStackWindowController;
import com.android.server.wm.StackWindowController;
import com.android.server.wm.TaskWindowContainerController;
import com.android.server.wm.WindowManagerService;
import com.android.server.wm.WindowTestUtils;
+
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.mockito.MockitoAnnotations;
-
+import org.mockito.invocation.InvocationOnMock;
/**
* A base class to handle common operations in activity related unit tests.
diff --git a/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java b/services/tests/wmtests/src/com/android/server/am/AppErrorDialogTest.java
similarity index 95%
rename from services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
rename to services/tests/wmtests/src/com/android/server/am/AppErrorDialogTest.java
index 3d11c4c..2289dfc 100644
--- a/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/AppErrorDialogTest.java
@@ -32,7 +32,10 @@
import java.io.File;
/**
- * runtest -c com.android.server.am.AppErrorDialogTest frameworks-services
+ * Tests for {@link AppErrorDialog}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:AppErrorDialogTest
*/
@RunWith(AndroidJUnit4.class)
@SmallTest
diff --git a/services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java b/services/tests/wmtests/src/com/android/server/am/AssistDataRequesterTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java
rename to services/tests/wmtests/src/com/android/server/am/AssistDataRequesterTest.java
index ce88d84..285a84f 100644
--- a/services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/AssistDataRequesterTest.java
@@ -62,7 +62,8 @@
* Note: Currently, we only support fetching the screenshot for the current application, so the
* screenshot checks are hardcoded accordingly.
*
- * runtest --path frameworks/base/services/tests/servicestests/src/com/android/server/am/AssistDataRequesterTest.java
+ * Build/Install/Run:
+ * atest WmTests:AssistDataRequesterTest
*/
@MediumTest
@RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/am/ClientLifecycleManagerTests.java b/services/tests/wmtests/src/com/android/server/am/ClientLifecycleManagerTests.java
similarity index 66%
rename from services/tests/servicestests/src/com/android/server/am/ClientLifecycleManagerTests.java
rename to services/tests/wmtests/src/com/android/server/am/ClientLifecycleManagerTests.java
index ef6d5e8..3098db2 100644
--- a/services/tests/servicestests/src/com/android/server/am/ClientLifecycleManagerTests.java
+++ b/services/tests/wmtests/src/com/android/server/am/ClientLifecycleManagerTests.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 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 com.android.server.am;
import static org.mockito.Mockito.mock;
@@ -15,6 +31,12 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+/**
+ * Test class for {@link ClientLifecycleManager}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:ClientLifecycleManagerTests
+ */
@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java b/services/tests/wmtests/src/com/android/server/am/CoreSettingsObserverTest.java
similarity index 91%
rename from services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java
rename to services/tests/wmtests/src/com/android/server/am/CoreSettingsObserverTest.java
index da30c11..adf3f94 100644
--- a/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/CoreSettingsObserverTest.java
@@ -37,7 +37,6 @@
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -48,17 +47,8 @@
/**
* Test class for {@link CoreSettingsObserver}.
*
- * To run the tests, use
- *
- * runtest -c com.android.server.am.CoreSettingsObserverTest frameworks-services
- *
- * or the following steps:
- *
- * Build: m FrameworksServicesTests
- * Install: adb install -r \
- * ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
- * Run: adb shell am instrument -e class com.android.server.am.CoreSettingsObserverTest -w \
- * com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
+ * Build/Install/Run:
+ * atest WmTests:CoreSettingsObserverTest
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java b/services/tests/wmtests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java
similarity index 97%
rename from services/tests/servicestests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java
rename to services/tests/wmtests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java
index d9b3e1c..b1e0b51 100644
--- a/services/tests/servicestests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java
@@ -36,6 +36,9 @@
/**
* Tests for {@link GlobalSettingsToPropertiesMapper}
+ *
+ * Build/Install/Run:
+ * atest WmTests:GlobalSettingsToPropertiesMapperTest
*/
@RunWith(AndroidJUnit4.class)
@SmallTest
diff --git a/services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java b/services/tests/wmtests/src/com/android/server/am/LaunchParamsControllerTests.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java
rename to services/tests/wmtests/src/com/android/server/am/LaunchParamsControllerTests.java
index 161c287..5f2bc4d 100644
--- a/services/tests/servicestests/src/com/android/server/am/LaunchParamsControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/am/LaunchParamsControllerTests.java
@@ -16,20 +16,14 @@
package com.android.server.am;
-import android.app.ActivityOptions;
-import android.content.pm.ActivityInfo.WindowLayout;
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import com.android.server.am.LaunchParamsController.LaunchParams;
-import org.junit.runner.RunWith;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.android.server.am.LaunchParamsController.LaunchParamsModifier;
-
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
+import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doNothing;
@@ -40,18 +34,24 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
-import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
+import android.app.ActivityOptions;
+import android.content.pm.ActivityInfo.WindowLayout;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import com.android.server.am.LaunchParamsController.LaunchParams;
+import com.android.server.am.LaunchParamsController.LaunchParamsModifier;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Tests for exercising {@link LaunchParamsController}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:LaunchParamsControllerTests
+ * atest WmTests:LaunchParamsControllerTests
*/
@MediumTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java b/services/tests/wmtests/src/com/android/server/am/LockTaskControllerTest.java
similarity index 97%
rename from services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java
rename to services/tests/wmtests/src/com/android/server/am/LockTaskControllerTest.java
index f46d712..a2e9769 100644
--- a/services/tests/servicestests/src/com/android/server/am/LockTaskControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/LockTaskControllerTest.java
@@ -35,9 +35,20 @@
import static com.android.server.am.LockTaskController.STATUS_BAR_MASK_LOCKED;
import static com.android.server.am.LockTaskController.STATUS_BAR_MASK_PINNED;
-import static org.junit.Assert.*;
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.StatusBarManager;
import android.app.admin.DevicePolicyManager;
@@ -76,7 +87,7 @@
* Unit tests for {@link LockTaskController}.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.am.LockTaskControllerTest
+ * bit WmTests:LockTaskControllerTest
*/
@Presubmit
@SmallTest
diff --git a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java b/services/tests/wmtests/src/com/android/server/am/MemoryStatUtilTest.java
similarity index 97%
rename from services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
rename to services/tests/wmtests/src/com/android/server/am/MemoryStatUtilTest.java
index 5518ca5..18b0988 100644
--- a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/MemoryStatUtilTest.java
@@ -16,9 +16,9 @@
package com.android.server.am;
+import static com.android.server.am.MemoryStatUtil.MemoryStat;
import static com.android.server.am.MemoryStatUtil.parseMemoryStatFromMemcg;
import static com.android.server.am.MemoryStatUtil.parseMemoryStatFromProcfs;
-import static com.android.server.am.MemoryStatUtil.MemoryStat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@@ -29,6 +29,12 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+/**
+ * Tests for {@link MemoryStatUtil}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:MemoryStatUtilTest
+ */
@RunWith(AndroidJUnit4.class)
@SmallTest
public class MemoryStatUtilTest {
diff --git a/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java b/services/tests/wmtests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java
similarity index 96%
rename from services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java
rename to services/tests/wmtests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java
index 2baf995..f812ee6 100644
--- a/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java
@@ -20,14 +20,11 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
-import android.annotation.Nullable;
import android.app.ActivityOptions;
-import android.os.Handler;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.FlakyTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.util.ArrayMap;
import android.view.RemoteAnimationAdapter;
import com.android.server.testutils.OffsettableClock;
@@ -40,7 +37,10 @@
import org.mockito.MockitoAnnotations;
/**
- * atest PendingRemoteAnimationRegistryTest
+ * Tests for {@link PendingRemoteAnimationRegistry}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:PendingRemoteAnimationRegistryTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/am/PersistentConnectionTest.java b/services/tests/wmtests/src/com/android/server/am/PersistentConnectionTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/am/PersistentConnectionTest.java
rename to services/tests/wmtests/src/com/android/server/am/PersistentConnectionTest.java
index 54f93a8..5c42081 100644
--- a/services/tests/servicestests/src/com/android/server/am/PersistentConnectionTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/PersistentConnectionTest.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.server.am;
import static org.mockito.ArgumentMatchers.any;
@@ -41,6 +42,12 @@
import java.util.Arrays;
import java.util.Collections;
+/**
+ * Tests for {@link PersistentConnection}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:PersistentConnectionTest
+ */
@SmallTest
public class PersistentConnectionTest extends AndroidTestCase {
private static class MyConnection extends PersistentConnection<IDeviceAdminService> {
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/am/RecentTasksTest.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
rename to services/tests/wmtests/src/com/android/server/am/RecentTasksTest.java
index b73ac89..739467a 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/RecentTasksTest.java
@@ -35,16 +35,12 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
import static java.lang.Integer.MAX_VALUE;
-import android.annotation.TestApi;
import android.app.ActivityManager;
import android.app.ActivityManager.RecentTaskInfo;
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -53,7 +49,6 @@
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
-import android.os.Debug;
import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -80,7 +75,10 @@
import java.util.Set;
/**
- * atest FrameworksServicesTests:RecentTasksTest
+ * Tests for {@link RecentTasks}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:RecentTasksTest
*/
@MediumTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/am/RecentsAnimationTest.java
similarity index 93%
rename from services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java
rename to services/tests/wmtests/src/com/android/server/am/RecentsAnimationTest.java
index eefd973..ee576e3 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/RecentsAnimationTest.java
@@ -16,15 +16,13 @@
package com.android.server.am;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
-import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
+
import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
@@ -39,13 +37,18 @@
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.IRecentsAnimationRunner;
+
import com.android.server.AttributeCache;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
- * atest FrameworksServicesTests:RecentsAnimationTest
+ * Tests for {@link RecentsAnimation}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:RecentsAnimationTest
*/
@MediumTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/am/RunningTasksTest.java
similarity index 97%
rename from services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
rename to services/tests/wmtests/src/com/android/server/am/RunningTasksTest.java
index c6ce7e1..4e5fbd8 100644
--- a/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/RunningTasksTest.java
@@ -41,8 +41,11 @@
import java.util.ArrayList;
-/**
- * runtest --path frameworks/base/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
+ /**
+ * Tests for {@link RunningTasks}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:RunningTasksTest
*/
@MediumTest
@Presubmit
@@ -123,4 +126,4 @@
.build();
return task;
}
-}
\ No newline at end of file
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java b/services/tests/wmtests/src/com/android/server/am/SafeActivityOptionsTest.java
similarity index 92%
rename from services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java
rename to services/tests/wmtests/src/com/android/server/am/SafeActivityOptionsTest.java
index 168bc17..3f05c8c 100644
--- a/services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/SafeActivityOptionsTest.java
@@ -27,6 +27,12 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+/**
+ * Tests for {@link SafeActivityOptions}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:SafeActivityOptionsTest
+ */
@MediumTest
@Presubmit
@FlakyTest
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
similarity index 96%
rename from services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
rename to services/tests/wmtests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
index 3d323f0..7fb63d3 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/am/TaskLaunchParamsModifierTests.java
@@ -16,37 +16,29 @@
package com.android.server.am;
-import android.content.pm.ActivityInfo.WindowLayout;
-import android.graphics.Rect;
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import android.view.Gravity;
-
-import org.junit.runner.RunWith;
-import org.junit.Before;
-import org.junit.Test;
-
-import org.mockito.invocation.InvocationOnMock;
-
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static com.android.server.am.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.doAnswer;
import static org.junit.Assert.assertEquals;
+import android.content.pm.ActivityInfo.WindowLayout;
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.Gravity;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Tests for exercising resizing task bounds.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:TaskLaunchParamsModifierTests
+ * atest WmTests:TaskLaunchParamsModifierTests
*/
@MediumTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java b/services/tests/wmtests/src/com/android/server/am/TaskPersisterTest.java
similarity index 93%
rename from services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java
rename to services/tests/wmtests/src/com/android/server/am/TaskPersisterTest.java
index 9e6055d..cdafb52 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/TaskPersisterTest.java
@@ -17,20 +17,16 @@
package com.android.server.am;
import android.content.pm.UserInfo;
-import android.os.Environment;
import android.os.UserHandle;
import android.os.UserManager;
import android.test.AndroidTestCase;
-import android.util.Log;
import android.util.SparseBooleanArray;
-import com.android.server.am.TaskPersister;
-
-import java.io.File;
-import java.util.Random;
-
/**
- * atest FrameworksServicesTests:TaskPersisterTest
+ * Tests for {@link TaskPersister}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:TaskPersisterTest
*/
public class TaskPersisterTest extends AndroidTestCase {
private static final String TEST_USER_NAME = "AM-Test-User";
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/am/TaskRecordTests.java
similarity index 95%
rename from services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java
rename to services/tests/wmtests/src/com/android/server/am/TaskRecordTests.java
index 057fdc8..dbb3e7e 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/am/TaskRecordTests.java
@@ -29,20 +29,16 @@
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
-import android.content.res.XmlResourceParser;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.service.voice.IVoiceInteractionSession;
-import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.util.Xml;
-import com.android.frameworks.servicestests.R;
import com.android.internal.app.IVoiceInteractor;
import com.android.server.am.TaskRecord.TaskRecordFactory;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -57,15 +53,13 @@
import java.io.IOException;
import java.io.OutputStream;
import java.io.Reader;
-import java.nio.file.Files;
import java.util.ArrayList;
-import java.util.Comparator;
/**
* Tests for exercising {@link TaskRecord}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:com.android.server.am.TaskRecordTests
+ * atest WmTests:TaskRecordTests
*/
@MediumTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/am/TaskStackChangedListenerTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java
rename to services/tests/wmtests/src/com/android/server/am/TaskStackChangedListenerTest.java
index 0359096..28689cb 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskStackChangedListenerTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/TaskStackChangedListenerTest.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import static android.support.test.InstrumentationRegistry.getInstrumentation;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -32,23 +33,30 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
-import android.content.res.Resources.Theme;
import android.os.RemoteException;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiDevice;
import android.text.TextUtils;
-import android.util.Pair;
+
import com.android.internal.annotations.GuardedBy;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
+
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests for {@link TaskStackListener}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:TaskStackChangedListenerTest
+ */
@MediumTest
@RunWith(AndroidJUnit4.class)
public class TaskStackChangedListenerTest {
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/wmtests/src/com/android/server/am/UserControllerTest.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
rename to services/tests/wmtests/src/com/android/server/am/UserControllerTest.java
index cc4f519..fb5ded5 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/am/UserControllerTest.java
@@ -16,6 +16,30 @@
package com.android.server.am;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareClassLoader;
+
+import static com.android.server.am.UserController.CONTINUE_USER_SWITCH_MSG;
+import static com.android.server.am.UserController.REPORT_LOCKED_BOOT_COMPLETE_MSG;
+import static com.android.server.am.UserController.REPORT_USER_SWITCH_COMPLETE_MSG;
+import static com.android.server.am.UserController.REPORT_USER_SWITCH_MSG;
+import static com.android.server.am.UserController.SYSTEM_USER_CURRENT_MSG;
+import static com.android.server.am.UserController.SYSTEM_USER_START_MSG;
+import static com.android.server.am.UserController.USER_SWITCH_TIMEOUT_MSG;
+
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
import android.app.IUserSwitchObserver;
import android.content.Context;
import android.content.IIntentReceiver;
@@ -48,30 +72,11 @@
import java.util.List;
import java.util.Set;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.testing.DexmakerShareClassLoaderRule.runWithDexmakerShareClassLoader;
-import static com.android.server.am.UserController.CONTINUE_USER_SWITCH_MSG;
-import static com.android.server.am.UserController.REPORT_LOCKED_BOOT_COMPLETE_MSG;
-import static com.android.server.am.UserController.REPORT_USER_SWITCH_COMPLETE_MSG;
-import static com.android.server.am.UserController.REPORT_USER_SWITCH_MSG;
-import static com.android.server.am.UserController.SYSTEM_USER_CURRENT_MSG;
-import static com.android.server.am.UserController.SYSTEM_USER_START_MSG;
-import static com.android.server.am.UserController.USER_SWITCH_TIMEOUT_MSG;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.when;
-
/**
- * Usage: bit FrameworksServicesTests:com.android.server.am.UserControllerTest
+ * Tests for {@link UserController}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:UserControllerTest
*/
@Presubmit
public class UserControllerTest extends AndroidTestCase {
diff --git a/services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java b/services/tests/wmtests/src/com/android/server/policy/FakeWindowState.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/policy/FakeWindowState.java
rename to services/tests/wmtests/src/com/android/server/policy/FakeWindowState.java
diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerInsetsTest.java b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerInsetsTest.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerInsetsTest.java
rename to services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerInsetsTest.java
diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerLayoutTest.java b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerLayoutTest.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerLayoutTest.java
rename to services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerLayoutTest.java
diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTest.java b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTest.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTest.java
rename to services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTest.java
diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
rename to services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java b/services/tests/wmtests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
similarity index 89%
rename from services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
rename to services/tests/wmtests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
index 164c80b..a396946 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
@@ -18,13 +18,10 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.mockito.ArgumentMatchers.any;
+
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
@@ -33,12 +30,9 @@
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -46,7 +40,7 @@
* Tests for the {@link TaskStack} class.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:com.android.server.wm.AnimatingAppWindowTokenRegistryTest
+ * atest WmTests:AnimatingAppWindowTokenRegistryTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java
rename to services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index be7d781..6b3266d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -20,6 +20,7 @@
import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
+
import static org.junit.Assert.assertEquals;
import android.content.Context;
@@ -36,7 +37,8 @@
/**
* Test class for {@link AppTransition}.
*
- * atest AppTransitionTests
+ * Build/Install/Run:
+ * atest WmTests:AppTransitionTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowContainerControllerTests.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
rename to services/tests/wmtests/src/com/android/server/wm/AppWindowContainerControllerTests.java
index e0645b1..09a0847 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowContainerControllerTests.java
@@ -16,30 +16,32 @@
package com.android.server.wm;
-import android.support.test.filters.FlakyTest;
-import org.junit.Test;
-
-import android.platform.test.annotations.Presubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.EMPTY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.FlakyTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
import com.android.server.wm.WindowTestUtils.TestTaskWindowContainerController;
+import org.junit.Test;
+
/**
* Test class for {@link AppWindowContainerController}.
*
- * atest FrameworksServicesTests:com.android.server.wm.AppWindowContainerControllerTests
+ * Build/Install/Run:
+ * atest WmTests:AppWindowContainerControllerTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
rename to services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index f6599dc..8dedb584a 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -16,16 +16,6 @@
package com.android.server.wm;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.view.Surface;
-import android.view.WindowManager;
-
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
@@ -38,15 +28,27 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.TRANSIT_UNSET;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.FlakyTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.Surface;
+import android.view.WindowManager;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
/**
* Tests for the {@link AppWindowToken} class.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:com.android.server.wm.AppWindowTokenTests
+ * atest WmTests:AppWindowTokenTests
*/
@SmallTest
// TODO: b/68267650
diff --git a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
rename to services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java
index ff631e7..7fbb4ee 100644
--- a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java
@@ -21,6 +21,12 @@
import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START;
import static com.android.server.wm.BoundsAnimationController.SchedulePipModeChangedState;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Rect;
@@ -32,23 +38,12 @@
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import com.android.server.wm.BoundsAnimationController.BoundsAnimator;
import com.android.server.wm.WindowManagerInternal.AppTransitionListener;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import com.android.server.wm.BoundsAnimationController.BoundsAnimator;
-
/**
* Test class for {@link BoundsAnimationController} to ensure that it sends the right callbacks
* depending on the various interactions.
@@ -60,7 +55,7 @@
* appropriately.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.BoundsAnimationControllerTests
+ * bit WmTests:BoundsAnimationControllerTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/ConfigurationContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/ConfigurationContainerTests.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/wm/ConfigurationContainerTests.java
rename to services/tests/wmtests/src/com/android/server/wm/ConfigurationContainerTests.java
index 192e156..6a6f954 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ConfigurationContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ConfigurationContainerTests.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
@@ -28,6 +27,7 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
import static android.content.res.Configuration.EMPTY;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -35,6 +35,7 @@
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -45,7 +46,7 @@
* Test class for {@link ConfigurationContainer}.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.ConfigurationContainerTests
+ * atest WmTests:ConfigurationContainerTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
rename to services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
index 6769e40..a12a802f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
@@ -38,8 +38,10 @@
import org.junit.runner.RunWith;
/**
+ * Tests for {@link Dimmer}.
+ *
* Build/Install/Run:
- * atest FrameworksServicesTests:com.android.server.wm.DimmerTests;
+ * atest WmTests:DimmerTests;
*/
@Presubmit
@RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
rename to services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index ac196f9..a9744ea 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -28,6 +28,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
+
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static org.hamcrest.Matchers.is;
@@ -38,9 +39,6 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
import android.annotation.SuppressLint;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -57,6 +55,9 @@
import com.android.server.wm.utils.WmDisplayCutout;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -67,7 +68,7 @@
* Tests for the {@link DisplayContent} class.
*
* Build/Install/Run:
- * atest com.android.server.wm.DisplayContentTests
+ * atest WmTests:DisplayContentTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
rename to services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
index a09656c..68b0998 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
@@ -39,19 +40,23 @@
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.View;
+
import com.android.internal.annotations.GuardedBy;
import com.android.server.LocalServices;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
/**
* Tests for the {@link DragDropController} class.
*
- * atest com.android.server.wm.DragDropControllerTests
+ * Build/Install/Run:
+ * atest WmTests:DragDropControllerTests
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/wm/PinnedStackControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java
similarity index 94%
rename from services/tests/servicestests/src/com/android/server/wm/PinnedStackControllerTest.java
rename to services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java
index 96745fa..f0faf28 100644
--- a/services/tests/servicestests/src/com/android/server/wm/PinnedStackControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java
@@ -2,6 +2,15 @@
import static android.view.Display.DEFAULT_DISPLAY;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
@@ -14,15 +23,12 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
+/**
+ * Tests for {@link PinnedStackController}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:PinnedStackControllerTest
+ */
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
similarity index 97%
rename from services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java
rename to services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index a2af9b8..fdebaa6 100644
--- a/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -19,8 +19,10 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.Display.DEFAULT_DISPLAY;
+
import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
+
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeast;
@@ -35,7 +37,9 @@
import android.support.test.runner.AndroidJUnit4;
import android.view.IRecentsAnimationRunner;
import android.view.SurfaceControl;
+
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -43,7 +47,10 @@
import org.mockito.MockitoAnnotations;
/**
- * atest FrameworksServicesTests:com.android.server.wm.RecentsAnimationControllerTest
+ * Tests for {@link RecentsAnimationController}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:RecentsAnimationControllerTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java
rename to services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index 95361f0..383e53f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -31,7 +31,6 @@
import android.os.Binder;
import android.os.IInterface;
import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.IRemoteAnimationFinishedCallback;
@@ -53,7 +52,10 @@
import org.mockito.MockitoAnnotations;
/**
- * atest FrameworksServicesTests:com.android.server.wm.RemoteAnimationControllerTest
+ * Tests for {@link RemoteAnimationController}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:RemoteAnimationControllerTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
similarity index 95%
rename from services/tests/servicestests/src/com/android/server/wm/RootWindowContainerTests.java
rename to services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 204e26c..317f36c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -1,22 +1,21 @@
package com.android.server.wm;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import static org.junit.Assert.assertTrue;
import android.content.res.Configuration;
import android.graphics.Rect;
-
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Tests for the {@link RootWindowContainer} class.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:com.android.server.wm.RootWindowContainerTests
+ * atest WmTests:RootWindowContainerTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java b/services/tests/wmtests/src/com/android/server/wm/ScreenDecorWindowTests.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java
rename to services/tests/wmtests/src/com/android/server/wm/ScreenDecorWindowTests.java
index a2ccee4..7e7cfed 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ScreenDecorWindowTests.java
@@ -32,6 +32,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
import static org.junit.Assert.assertEquals;
import android.app.Activity;
@@ -70,7 +71,7 @@
* Tests for the {@link android.view.WindowManager.LayoutParams#PRIVATE_FLAG_IS_SCREEN_DECOR} flag.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:com.android.server.wm.ScreenDecorWindowTests
+ * atest WmTests:ScreenDecorWindowTests
*/
// TODO: Add test for FLAG_FULLSCREEN which hides the status bar and also other flags.
// TODO: Test non-Activity windows.
diff --git a/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/StackWindowControllerTests.java
similarity index 97%
rename from services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
rename to services/tests/wmtests/src/com/android/server/wm/StackWindowControllerTests.java
index ab0a2bd..fb2986c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/StackWindowControllerTests.java
@@ -16,25 +16,24 @@
package com.android.server.wm;
-import android.graphics.Rect;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
/**
* Test class for {@link StackWindowController}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:StackWindowControllerTests
+ * atest WmTests:StackWindowControllerTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
similarity index 96%
rename from services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
rename to services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
index edac8a5..9ea3702 100644
--- a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -24,11 +23,11 @@
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.animation.AnimationHandler;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
import android.animation.AnimationHandler.AnimationFrameCallbackProvider;
import android.animation.ValueAnimator;
import android.graphics.Matrix;
@@ -37,7 +36,6 @@
import android.support.test.filters.FlakyTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.util.Log;
import android.view.Choreographer;
import android.view.Choreographer.FrameCallback;
import android.view.SurfaceControl;
@@ -46,7 +44,6 @@
import android.view.animation.TranslateAnimation;
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
-import com.android.server.wm.SurfaceAnimationRunner.AnimatorFactory;
import org.junit.Before;
import org.junit.Rule;
@@ -61,7 +58,8 @@
/**
* Test class for {@link SurfaceAnimationRunner}.
*
- * atest FrameworksServicesTests:com.android.server.wm.SurfaceAnimationRunnerTest
+ * Build/Install/Run:
+ * atest WmTests:SurfaceAnimationRunnerTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
rename to services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
index 16b8458..66f4b194 100644
--- a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
@@ -46,12 +46,11 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.ArrayList;
-
/**
* Test class for {@link SurfaceAnimatorTest}.
*
- * atest FrameworksServicesTests:com.android.server.wm.SurfaceAnimatorTest
+ * Build/Install/Run:
+ * atest WmTests:SurfaceAnimatorTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
rename to services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
index 7bf7dd7..ae73089 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
@@ -16,10 +16,14 @@
package com.android.server.wm;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import static com.android.server.wm.TaskPositioner.MIN_ASPECT;
+import static com.android.server.wm.WindowManagerService.dipToPixel;
+import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
+import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import android.graphics.Rect;
import android.support.test.filters.SmallTest;
@@ -28,18 +32,16 @@
import android.util.Log;
import android.view.Display;
-import static com.android.server.wm.TaskPositioner.MIN_ASPECT;
-import static com.android.server.wm.WindowManagerService.dipToPixel;
-import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
-import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Tests for the {@link TaskPositioner} class.
*
- * runtest frameworks-services -c com.android.server.wm.TaskPositionerTests
+ * Build/Install/Run:
+ * atest WmTests:TaskPositionerTests
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
similarity index 97%
rename from services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java
rename to services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
index 6070516..659ec41 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -30,6 +31,7 @@
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.InputChannel;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -37,7 +39,8 @@
/**
* Tests for the {@link TaskPositioningController} class.
*
- * atest com.android.server.wm.TaskPositioningControllerTests
+ * Build/Install/Run:
+ * atest WmTests:TaskPositioningControllerTests
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java
rename to services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
index 649de4a..1aefa277 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
+
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
@@ -31,7 +32,8 @@
/**
* Test class for {@link TaskSnapshotCache}.
*
- * runtest frameworks-services -c com.android.server.wm.TaskSnapshotCacheTest
+ * Build/Install/Run:
+ * atest WmTests:TaskSnapshotCacheTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
similarity index 95%
rename from services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
rename to services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 5650050..77521a6 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -19,10 +19,11 @@
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.TRANSIT_UNSET;
-import static com.android.server.wm.TaskSnapshotController.*;
+
+import static com.android.server.wm.TaskSnapshotController.SNAPSHOT_MODE_APP_THEME;
+import static com.android.server.wm.TaskSnapshotController.SNAPSHOT_MODE_REAL;
+
import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
@@ -30,13 +31,15 @@
import android.util.ArraySet;
import com.google.android.collect.Sets;
+
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Test class for {@link TaskSnapshotController}.
*
- * runtest frameworks-services -c com.android.server.wm.TaskSnapshotControllerTest
+ * Build/Install/Run:
+ * atest WmTests:TaskSnapshotControllerTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
rename to services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
index 325d42a..ed81daf 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
@@ -18,12 +18,12 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
import android.app.ActivityManager.TaskSnapshot;
import android.content.res.Configuration;
@@ -33,8 +33,8 @@
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.util.ArraySet;
-
import android.view.View;
+
import com.android.server.wm.TaskSnapshotPersister.RemoveObsoleteFilesQueueItem;
import org.junit.Test;
@@ -45,7 +45,8 @@
/**
* Test class for {@link TaskSnapshotPersister} and {@link TaskSnapshotLoader}
*
- * atest FrameworksServicesTests:TaskSnapshotPersisterLoaderTest
+ * Build/Install/Run:
+ * atest WmTests:TaskSnapshotPersisterLoaderTest
*/
@MediumTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
rename to services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
rename to services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index b19373e..287fff5 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
@@ -47,7 +48,8 @@
/**
* Test class for {@link TaskSnapshotSurface}.
*
- * runtest frameworks-services -c com.android.server.wm.TaskSnapshotSurfaceTest
+ * Build/Install/Run:
+ * atest WmTests:TaskSnapshotSurfaceTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
similarity index 96%
rename from services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
rename to services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
index ca1994f..e66b0d9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -18,26 +18,25 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.Before;
-import org.junit.After;
-
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
/**
* Tests for the {@link DisplayContent.TaskStackContainers} container in {@link DisplayContent}.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.TaskStackContainersTests
+ * atest WmTests:TaskStackContainersTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
similarity index 95%
rename from services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
rename to services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index eaf71f0..0deb4af 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -16,27 +16,24 @@
package com.android.server.wm;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Tests for the {@link TaskStack} class.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.TaskStackTests
+ * atest WmTests:TaskStackTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
rename to services/tests/wmtests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
index 1dd9365..e734bc0 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
@@ -16,22 +16,23 @@
package com.android.server.wm;
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
/**
* Test class for {@link TaskWindowContainerController}.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.TaskWindowContainerControllerTests
+ * atest WmTests:TaskWindowContainerControllerTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
rename to services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
index 353aa7d..032f416 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
@@ -16,8 +16,6 @@
package com.android.server.wm;
-import com.android.internal.os.IResultReceiver;
-
import android.graphics.Rect;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
@@ -27,6 +25,8 @@
import android.view.DragEvent;
import android.view.IWindow;
+import com.android.internal.os.IResultReceiver;
+
public class TestIWindow extends IWindow.Stub {
@Override
public void executeCommand(String command, String parameters,
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
rename to services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
similarity index 97%
rename from services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
rename to services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index a5c47de..903352b 100644
--- a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -29,7 +29,8 @@
/**
* Test class for {@link AppTransition}.
*
- * runtest frameworks-services -c com.android.server.wm.UnknownAppVisibilityControllerTest
+ * Build/Install/Run:
+ * atest WmTests:UnknownAppVisibilityControllerTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/wm/WallpaperControllerTests.java
rename to services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
rename to services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java
index ca520ed..aac905e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowAnimationSpecTest.java
@@ -40,7 +40,8 @@
/**
* Tests for the {@link WindowAnimationSpec} class.
*
- * atest FrameworksServicesTests:com.android.server.wm.WindowAnimationSpecTest
+ * Build/Install/Run:
+ * atest WmTests:WindowAnimationSpecTest
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java
rename to services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
index 513c1ec..9c59a17 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
@@ -16,7 +16,16 @@
package com.android.server.wm;
-import org.junit.Test;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS;
+import static android.app.WindowConfiguration.WINDOW_CONFIG_WINDOWING_MODE;
+import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import android.app.WindowConfiguration;
import android.content.res.Configuration;
@@ -27,22 +36,13 @@
import android.support.test.runner.AndroidJUnit4;
import android.view.DisplayInfo;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS;
-import static android.app.WindowConfiguration.WINDOW_CONFIG_WINDOWING_MODE;
-import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertTrue;
+import org.junit.Test;
/**
* Test class to for {@link android.app.WindowConfiguration}.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.WindowConfigurationTests
+ * atest WmTests:WindowConfigurationTests
*/
@SmallTest
@FlakyTest(bugId = 74078662)
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java
similarity index 96%
rename from services/tests/servicestests/src/com/android/server/wm/WindowContainerControllerTests.java
rename to services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java
index 502cb6e..05f7c34 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java
@@ -16,26 +16,26 @@
package com.android.server.wm;
-import android.app.WindowConfiguration;
-import android.content.res.Configuration;
-import android.support.test.filters.FlakyTest;
-import org.junit.Test;
-
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.content.res.Configuration.EMPTY;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import android.content.res.Configuration;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.FlakyTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+
/**
* Test class for {@link WindowContainerController}.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.WindowContainerControllerTests
+ * atest WmTests:WindowContainerControllerTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
rename to services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index 6c7830e..5beeee1 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -16,20 +16,6 @@
package com.android.server.wm;
-import android.support.test.filters.FlakyTest;
-import android.view.SurfaceControl;
-import android.view.SurfaceSession;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import java.util.Comparator;
-
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
@@ -44,7 +30,6 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyFloat;
import static org.mockito.Mockito.eq;
@@ -53,11 +38,25 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.FlakyTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Comparator;
+
/**
* Test class for {@link WindowContainer}.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:com.android.server.wm.WindowContainerTests
+ * atest WmTests:WindowContainerTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
similarity index 96%
rename from services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java
rename to services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
index e076399..e1acd78 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
@@ -20,9 +20,10 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import static org.mockito.Matchers.eq;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
@@ -31,12 +32,13 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
-
import java.util.function.Consumer;
/**
* Tests for {@link WindowContainer#forAllWindows} and various implementations.
+ *
+ * Build/Install/Run:
+ * atest WmTests:WindowContainerTraversalTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
rename to services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index 5a56332..6a00de4 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -16,9 +16,12 @@
package com.android.server.wm;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import static android.view.DisplayCutout.fromBoundingRect;
+import static android.view.WindowManager.LayoutParams.FILL_PARENT;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import android.app.ActivityManager.TaskDescription;
import android.content.res.Configuration;
@@ -31,18 +34,17 @@
import android.view.IWindow;
import android.view.WindowManager;
-import static android.view.DisplayCutout.fromBoundingRect;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.FILL_PARENT;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
import com.android.server.wm.utils.WmDisplayCutout;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
/**
* Tests for the {@link WindowState#computeFrameLw} method and other window frame machinery.
*
- * Build/Install/Run: bit FrameworksServicesTests:com.android.server.wm.WindowFrameTests
+ * Build/Install/Run:
+ * atest WmTests:WindowFrameTests
*/
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRule.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
rename to services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRule.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRuleTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRuleTest.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRuleTest.java
rename to services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRuleTest.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
rename to services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 85e846d..0f07e7e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -16,17 +16,6 @@
package com.android.server.wm;
-import android.view.WindowManager;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.FlakyTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import java.util.LinkedList;
-
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
@@ -55,10 +44,22 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.FlakyTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.WindowManager;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.LinkedList;
+
/**
* Tests for the {@link WindowState} class.
*
- * atest FrameworksServicesTests:com.android.server.wm.WindowStateTests
+ * Build/Install/Run:
+ * atest WmTests:WindowStateTests
*/
@SmallTest
@FlakyTest(bugId = 74078662)
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowSurfacePlacerTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowSurfacePlacerTest.java
similarity index 96%
rename from services/tests/servicestests/src/com/android/server/wm/WindowSurfacePlacerTest.java
rename to services/tests/wmtests/src/com/android/server/wm/WindowSurfacePlacerTest.java
index e173b7d..13f7916 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowSurfacePlacerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowSurfacePlacerTest.java
@@ -20,6 +20,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
import static android.view.WindowManager.TRANSIT_TASK_OPEN;
+
import static junit.framework.Assert.assertEquals;
import android.platform.test.annotations.Presubmit;
@@ -31,6 +32,12 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+/**
+ * Tests for {@link WindowSurfacePlacer}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:WindowSurfacePlacerTest
+ */
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
rename to services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index 2e4740b..6ab9c30 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -16,21 +16,12 @@
package com.android.server.wm;
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.os.Binder;
-import android.os.IBinder;
-import android.view.IApplicationToken;
-import android.view.IWindow;
-import android.view.WindowManager;
-
import static android.app.AppOpsManager.OP_NONE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
+
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyFloat;
@@ -39,6 +30,15 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Binder;
+import android.os.IBinder;
+import android.view.IApplicationToken;
+import android.view.IWindow;
+import android.view.WindowManager;
+
import org.mockito.invocation.InvocationOnMock;
/**
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
similarity index 100%
rename from services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
rename to services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
similarity index 97%
rename from services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
rename to services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
index e3b7174..5ea87b1 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
@@ -16,29 +16,29 @@
package com.android.server.wm;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.FlakyTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Tests for the {@link WindowToken} class.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.WindowTokenTests
+ * atest WmTests:WindowTokenTests
*/
@SmallTest
@FlakyTest(bugId = 74078662)
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTracingTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
similarity index 97%
rename from services/tests/servicestests/src/com/android/server/wm/WindowTracingTest.java
rename to services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
index 5085254..f60ae75 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTracingTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTracingTest.java
@@ -30,13 +30,12 @@
import android.content.Context;
import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
import android.support.test.filters.FlakyTest;
+import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.util.proto.ProtoOutputStream;
import com.android.internal.util.Preconditions;
-import com.android.server.wm.WindowManagerTraceProto;
import org.junit.After;
import org.junit.Before;
@@ -54,7 +53,7 @@
* Test class for {@link WindowTracing}.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.WindowTracingTest
+ * atest WmTests:WindowTracingTest
*/
@SmallTest
@FlakyTest(bugId = 74078662)
diff --git a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
rename to services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index 547be55..a730b5c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -27,15 +27,14 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
import android.platform.test.annotations.Presubmit;
-import android.support.test.filters.SmallTest;
import android.support.test.filters.FlakyTest;
+import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
@@ -51,7 +50,7 @@
* Tests for the {@link WindowLayersController} class.
*
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.ZOrderingTests
+ * atest WmTests:ZOrderingTests
*/
@SmallTest
@FlakyTest(bugId = 74078662)
diff --git a/services/tests/servicestests/src/com/android/server/wm/utils/CoordinateTransformsTest.java b/services/tests/wmtests/src/com/android/server/wm/utils/CoordinateTransformsTest.java
similarity index 91%
rename from services/tests/servicestests/src/com/android/server/wm/utils/CoordinateTransformsTest.java
rename to services/tests/wmtests/src/com/android/server/wm/utils/CoordinateTransformsTest.java
index 40a10e0..f0f3023 100644
--- a/services/tests/servicestests/src/com/android/server/wm/utils/CoordinateTransformsTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/utils/CoordinateTransformsTest.java
@@ -21,10 +21,11 @@
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
-import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
+import static com.android.server.wm.utils.CoordinateTransforms
+ .transformPhysicalToLogicalCoordinates;
import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertThat;
import android.graphics.Matrix;
import android.graphics.Point;
@@ -35,6 +36,12 @@
import org.junit.Test;
import org.junit.rules.ErrorCollector;
+/**
+ * Tests for {@link CoordinateTransforms}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:CoordinateTransformsTest
+ */
public class CoordinateTransformsTest {
private static final int W = 200;
@@ -95,4 +102,4 @@
public interface DevicePointAssertable {
void mapsToLogicalPoint(int x, int y);
}
-}
\ No newline at end of file
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java b/services/tests/wmtests/src/com/android/server/wm/utils/InsetUtilsTest.java
similarity index 92%
rename from services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java
rename to services/tests/wmtests/src/com/android/server/wm/utils/InsetUtilsTest.java
index d0f0fe3..ff3d883 100644
--- a/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/utils/InsetUtilsTest.java
@@ -22,11 +22,16 @@
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import android.util.Pair;
import org.junit.Test;
import org.junit.runner.RunWith;
+/**
+ * Tests for {@link InsetUtils}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:InsetUtilsTest
+ */
@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/utils/RotationCacheTest.java b/services/tests/wmtests/src/com/android/server/wm/utils/RotationCacheTest.java
similarity index 96%
rename from services/tests/servicestests/src/com/android/server/wm/utils/RotationCacheTest.java
rename to services/tests/wmtests/src/com/android/server/wm/utils/RotationCacheTest.java
index 6bbc7eb..c800fa2 100644
--- a/services/tests/servicestests/src/com/android/server/wm/utils/RotationCacheTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/utils/RotationCacheTest.java
@@ -29,13 +29,16 @@
import android.support.test.runner.AndroidJUnit4;
import android.util.Pair;
-import com.android.server.wm.utils.RotationCache.RotationDependentComputation;
-
-import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+/**
+ * Tests for {@link RotationCache}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:RotationCacheTest
+ */
@RunWith(AndroidJUnit4.class)
@SmallTest
@FlakyTest(bugId = 74078662)
diff --git a/services/tests/servicestests/src/com/android/server/wm/utils/WmDisplayCutoutTest.java b/services/tests/wmtests/src/com/android/server/wm/utils/WmDisplayCutoutTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/wm/utils/WmDisplayCutoutTest.java
rename to services/tests/wmtests/src/com/android/server/wm/utils/WmDisplayCutoutTest.java
index f7addf6..f4c208b 100644
--- a/services/tests/servicestests/src/com/android/server/wm/utils/WmDisplayCutoutTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/utils/WmDisplayCutoutTest.java
@@ -16,7 +16,6 @@
package com.android.server.wm.utils;
-
import static android.view.DisplayCutout.NO_CUTOUT;
import static android.view.DisplayCutout.fromBoundingRect;
@@ -38,7 +37,8 @@
/**
* Tests for {@link WmDisplayCutout}
*
- * Run with: atest WmDisplayCutoutTest
+ * Build/Install/Run:
+ * atest WmTests:WmDisplayCutoutTest
*/
@RunWith(AndroidJUnit4.class)
@SmallTest
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 36f8063..4da7285 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -539,7 +539,8 @@
// We do not show the USB notification if the primary volume supports mass storage.
// The legacy mass storage UI will be used instead.
final StorageManager storageManager = StorageManager.from(mContext);
- final StorageVolume primary = storageManager.getPrimaryVolume();
+ final StorageVolume primary =
+ storageManager != null ? storageManager.getPrimaryVolume() : null;
boolean massStorageSupported = primary != null && primary.allowMassStorage();
mUseUsbNotification = !massStorageSupported && mContext.getResources().getBoolean(
diff --git a/startop/iorap/Android.bp b/startop/iorap/Android.bp
new file mode 100644
index 0000000..b3b0900
--- /dev/null
+++ b/startop/iorap/Android.bp
@@ -0,0 +1,28 @@
+// Copyright (C) 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.
+
+java_library_static {
+ name: "libiorap-java",
+
+ aidl: {
+ include_dirs: [
+ "system/iorap/binder",
+ ],
+ },
+
+ srcs: [
+ ":iorap-aidl",
+ "**/*.java",
+ ],
+}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/ActivityHintEvent.java b/startop/iorap/src/com/google/android/startop/iorap/ActivityHintEvent.java
new file mode 100644
index 0000000..1d38f4c
--- /dev/null
+++ b/startop/iorap/src/com/google/android/startop/iorap/ActivityHintEvent.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 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 com.google.android.startop.iorap;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Provide a hint to iorapd that an activity has transitioned state.<br /><br />
+ *
+ * Knowledge of when an activity starts/stops can be used by iorapd to increase system
+ * performance (e.g. by launching perfetto tracing to record an io profile, or by
+ * playing back an ioprofile via readahead) over the long run.<br /><br />
+ *
+ * /@see com.google.android.startop.iorap.IIorap#onActivityHintEvent<br /><br />
+ *
+ * Once an activity hint is in {@link #TYPE_STARTED} it must transition to another type.
+ * All other states could be terminal, see below: <br /><br />
+ *
+ * <pre>
+ *
+ * ┌──────────────────────────────────────┐
+ * │ ▼
+ * ┌─────────┐ ╔════════════════╗ ╔═══════════╗
+ * ──▶ │ STARTED │ ──▶ ║ COMPLETED ║ ──▶ ║ CANCELLED ║
+ * └─────────┘ ╚════════════════╝ ╚═══════════╝
+ * │
+ * │
+ * ▼
+ * ╔════════════════╗
+ * ║ POST_COMPLETED ║
+ * ╚════════════════╝
+ *
+ * </pre> <!-- system/iorap/docs/binder/ActivityHint.dot -->
+ *
+ * @hide
+ */
+public class ActivityHintEvent implements Parcelable {
+
+ public static final int TYPE_STARTED = 0;
+ public static final int TYPE_CANCELLED = 1;
+ public static final int TYPE_COMPLETED = 2;
+ public static final int TYPE_POST_COMPLETED = 3;
+ private static final int TYPE_MAX = TYPE_POST_COMPLETED;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = { "TYPE_" }, value = {
+ TYPE_STARTED,
+ TYPE_CANCELLED,
+ TYPE_COMPLETED,
+ TYPE_POST_COMPLETED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Type {}
+
+ @Type public final int type;
+ public final ActivityInfo activityInfo;
+
+ public ActivityHintEvent(@Type int type, ActivityInfo activityInfo) {
+ this.type = type;
+ this.activityInfo = activityInfo;
+ checkConstructorArguments();
+ }
+
+ private void checkConstructorArguments() {
+ CheckHelpers.checkTypeInRange(type, TYPE_MAX);
+ Objects.requireNonNull(activityInfo, "activityInfo");
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{type: %d, activityInfo: %s}", type, activityInfo);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ } else if (other instanceof ActivityHintEvent) {
+ return equals((ActivityHintEvent) other);
+ }
+ return false;
+ }
+
+ private boolean equals(ActivityHintEvent other) {
+ return type == other.type &&
+ Objects.equals(activityInfo, other.activityInfo);
+ }
+
+ //<editor-fold desc="Binder boilerplate">
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(type);
+ activityInfo.writeToParcel(out, flags);
+ }
+
+ private ActivityHintEvent(Parcel in) {
+ this.type = in.readInt();
+ this.activityInfo = ActivityInfo.CREATOR.createFromParcel(in);
+ checkConstructorArguments();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<ActivityHintEvent> CREATOR
+ = new Parcelable.Creator<ActivityHintEvent>() {
+ public ActivityHintEvent createFromParcel(Parcel in) {
+ return new ActivityHintEvent(in);
+ }
+
+ public ActivityHintEvent[] newArray(int size) {
+ return new ActivityHintEvent[size];
+ }
+ };
+ //</editor-fold>
+}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/ActivityInfo.java b/startop/iorap/src/com/google/android/startop/iorap/ActivityInfo.java
new file mode 100644
index 0000000..f47a42c
--- /dev/null
+++ b/startop/iorap/src/com/google/android/startop/iorap/ActivityInfo.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 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 com.google.android.startop.iorap;
+
+import java.util.Objects;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+/**
+ * Provide minimal information for launched activities to iorap.<br /><br />
+ *
+ * This uniquely identifies a system-wide activity by providing the {@link #packageName} and
+ * {@link #activityName}.
+ *
+ * @see ActivityHintEvent
+ * @see AppIntentEvent
+ *
+ * @hide
+ */
+public class ActivityInfo implements Parcelable {
+
+ /** The name of the package, for example {@code com.android.calculator}. */
+ public final String packageName;
+ /** The name of the activity, for example {@code .activities.activity.MainActivity} */
+ public final String activityName;
+
+ public ActivityInfo(String packageName, String activityName) {
+ this.packageName = packageName;
+ this.activityName = activityName;
+
+ checkConstructorArguments();
+ }
+
+ private void checkConstructorArguments() {
+ Objects.requireNonNull(packageName, "packageName");
+ Objects.requireNonNull(activityName, "activityName");
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{packageName: %s, activityName: %s}", packageName, activityName);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ } else if (other instanceof ActivityInfo) {
+ return equals((ActivityInfo) other);
+ }
+ return false;
+ }
+
+ private boolean equals(ActivityInfo other) {
+ return Objects.equals(packageName, other.packageName) &&
+ Objects.equals(activityName, other.activityName);
+ }
+
+ //<editor-fold desc="Binder boilerplate">
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(packageName);
+ out.writeString(activityName);
+ }
+
+ private ActivityInfo(Parcel in) {
+ packageName = in.readString();
+ activityName = in.readString();
+
+ checkConstructorArguments();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<ActivityInfo> CREATOR
+ = new Parcelable.Creator<ActivityInfo>() {
+ public ActivityInfo createFromParcel(Parcel in) {
+ return new ActivityInfo(in);
+ }
+
+ public ActivityInfo[] newArray(int size) {
+ return new ActivityInfo[size];
+ }
+ };
+ //</editor-fold>
+}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/AppIntentEvent.java b/startop/iorap/src/com/google/android/startop/iorap/AppIntentEvent.java
new file mode 100644
index 0000000..1cd37b5
--- /dev/null
+++ b/startop/iorap/src/com/google/android/startop/iorap/AppIntentEvent.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 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 com.google.android.startop.iorap;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Notifications for iorapd specifying when a system-wide intent defaults change.<br /><br />
+ *
+ * Intent defaults provide a mechanism for an app to register itself as an automatic handler.
+ * For example the camera app might be registered as the default handler for
+ * {@link android.provider.MediaStore#INTENT_ACTION_STILL_IMAGE_CAMERA} intent. Subsequently,
+ * if an arbitrary other app requests for a still image camera photo to be taken, the system
+ * will launch the respective default camera app to be launched to handle that request.<br /><br />
+ *
+ * In some cases iorapd might need to know default intents, e.g. for boot-time pinning of
+ * applications that resolve from the default intent. If the application would now be resolved
+ * differently, iorapd would unpin the old application and pin the new application.<br /><br />
+ *
+ * @hide
+ */
+public class AppIntentEvent implements Parcelable {
+
+ /** @see android.content.Intent#CATEGORY_DEFAULT */
+ public static final int TYPE_DEFAULT_INTENT_CHANGED = 0;
+ private static final int TYPE_MAX = 0;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = { "TYPE_" }, value = {
+ TYPE_DEFAULT_INTENT_CHANGED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Type {}
+
+ @Type public final int type;
+
+ public final ActivityInfo oldActivityInfo;
+ public final ActivityInfo newActivityInfo;
+
+ // TODO: Probably need the corresponding action here as well.
+
+ public static AppIntentEvent createDefaultIntentChanged(ActivityInfo oldActivityInfo,
+ ActivityInfo newActivityInfo) {
+ return new AppIntentEvent(TYPE_DEFAULT_INTENT_CHANGED, oldActivityInfo,
+ newActivityInfo);
+ }
+
+ private AppIntentEvent(@Type int type, ActivityInfo oldActivityInfo,
+ ActivityInfo newActivityInfo) {
+ this.type = type;
+ this.oldActivityInfo = oldActivityInfo;
+ this.newActivityInfo = newActivityInfo;
+
+ checkConstructorArguments();
+ }
+
+ private void checkConstructorArguments() {
+ CheckHelpers.checkTypeInRange(type, TYPE_MAX);
+ Objects.requireNonNull(oldActivityInfo, "oldActivityInfo");
+ Objects.requireNonNull(oldActivityInfo, "newActivityInfo");
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{oldActivityInfo: %s, newActivityInfo: %s}", oldActivityInfo,
+ newActivityInfo);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ } else if (other instanceof AppIntentEvent) {
+ return equals((AppIntentEvent) other);
+ }
+ return false;
+ }
+
+ private boolean equals(AppIntentEvent other) {
+ return type == other.type &&
+ Objects.equals(oldActivityInfo, other.oldActivityInfo) &&
+ Objects.equals(newActivityInfo, other.newActivityInfo);
+ }
+
+ //<editor-fold desc="Binder boilerplate">
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(type);
+ oldActivityInfo.writeToParcel(out, flags);
+ newActivityInfo.writeToParcel(out, flags);
+ }
+
+ private AppIntentEvent(Parcel in) {
+ this.type = in.readInt();
+ this.oldActivityInfo = ActivityInfo.CREATOR.createFromParcel(in);
+ this.newActivityInfo = ActivityInfo.CREATOR.createFromParcel(in);
+
+ checkConstructorArguments();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<AppIntentEvent> CREATOR
+ = new Parcelable.Creator<AppIntentEvent>() {
+ public AppIntentEvent createFromParcel(Parcel in) {
+ return new AppIntentEvent(in);
+ }
+
+ public AppIntentEvent[] newArray(int size) {
+ return new AppIntentEvent[size];
+ }
+ };
+ //</editor-fold>
+}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/CheckHelpers.java b/startop/iorap/src/com/google/android/startop/iorap/CheckHelpers.java
new file mode 100644
index 0000000..34aedd7
--- /dev/null
+++ b/startop/iorap/src/com/google/android/startop/iorap/CheckHelpers.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 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 com.google.android.startop.iorap;
+
+/**
+ * Convenience short-hand to throw {@link IllegalAccessException} when the arguments
+ * are out-of-range.
+ */
+public class CheckHelpers {
+ /** @throws IllegalAccessException if {@param type} is not in {@code [0..maxValue]} */
+ public static void checkTypeInRange(int type, int maxValue) {
+ if (type < 0) {
+ throw new IllegalArgumentException(
+ String.format("type must be non-negative (value=%d)", type));
+ }
+ if (type > maxValue) {
+ throw new IllegalArgumentException(
+ String.format("type out of range (value=%d, max=%d)", type, maxValue));
+ }
+ }
+
+ /** @throws IllegalAccessException if {@param state} is not in {@code [0..maxValue]} */
+ public static void checkStateInRange(int state, int maxValue) {
+ if (state < 0) {
+ throw new IllegalArgumentException(
+ String.format("state must be non-negative (value=%d)", state));
+ }
+ if (state > maxValue) {
+ throw new IllegalArgumentException(
+ String.format("state out of range (value=%d, max=%d)", state, maxValue));
+ }
+ }
+}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/PackageEvent.java b/startop/iorap/src/com/google/android/startop/iorap/PackageEvent.java
new file mode 100644
index 0000000..aa4eea7
--- /dev/null
+++ b/startop/iorap/src/com/google/android/startop/iorap/PackageEvent.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 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 com.google.android.startop.iorap;
+
+import android.annotation.NonNull;
+import android.os.Parcelable;
+import android.os.Parcel;
+import android.net.Uri;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Forward package manager events to iorapd. <br /><br />
+ *
+ * Knowing when packages are modified by the system are a useful tidbit to help with performance:
+ * for example when a package is replaced, it could be a hint used to invalidate any collected
+ * io profiles used for prefetching or pinning.
+ *
+ * @hide
+ */
+public class PackageEvent implements Parcelable {
+
+ /** @see android.content.Intent#ACTION_PACKAGE_REPLACED */
+ public static final int TYPE_REPLACED = 0;
+ private static final int TYPE_MAX = 0;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = { "TYPE_" }, value = {
+ TYPE_REPLACED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Type {}
+
+ @Type public final int type;
+
+ /** The path that a package is installed in, for example {@code /data/app/.../base.apk}. */
+ public final Uri packageUri;
+ /** The name of the package, for example {@code com.android.calculator}. */
+ public final String packageName;
+
+ @NonNull
+ public static PackageEvent createReplaced(Uri packageUri, String packageName) {
+ return new PackageEvent(TYPE_REPLACED, packageUri, packageName);
+ }
+
+ private PackageEvent(@Type int type, Uri packageUri, String packageName) {
+ this.type = type;
+ this.packageUri = packageUri;
+ this.packageName = packageName;
+
+ checkConstructorArguments();
+ }
+
+ private void checkConstructorArguments() {
+ CheckHelpers.checkTypeInRange(type, TYPE_MAX);
+ Objects.requireNonNull(packageUri, "packageUri");
+ Objects.requireNonNull(packageName, "packageName");
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ } else if (other instanceof PackageEvent) {
+ return equals((PackageEvent) other);
+ }
+ return false;
+ }
+
+ private boolean equals(PackageEvent other) {
+ return type == other.type &&
+ Objects.equals(packageUri, other.packageUri) &&
+ Objects.equals(packageName, other.packageName);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{packageUri: %s, packageName: %s}", packageUri, packageName);
+ }
+
+ //<editor-fold desc="Binder boilerplate">
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(type);
+ packageUri.writeToParcel(out, flags);
+ out.writeString(packageName);
+ }
+
+ private PackageEvent(Parcel in) {
+ this.type = in.readInt();
+ this.packageUri = Uri.CREATOR.createFromParcel(in);
+ this.packageName = in.readString();
+
+ checkConstructorArguments();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<PackageEvent> CREATOR
+ = new Parcelable.Creator<PackageEvent>() {
+ public PackageEvent createFromParcel(Parcel in) {
+ return new PackageEvent(in);
+ }
+
+ public PackageEvent[] newArray(int size) {
+ return new PackageEvent[size];
+ }
+ };
+ //</editor-fold>
+}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/RequestId.java b/startop/iorap/src/com/google/android/startop/iorap/RequestId.java
new file mode 100644
index 0000000..2c79319
--- /dev/null
+++ b/startop/iorap/src/com/google/android/startop/iorap/RequestId.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 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 com.google.android.startop.iorap;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import android.annotation.NonNull;
+
+/**
+ * Uniquely identify an {@link com.google.android.startop.iorap.IIorap} method invocation,
+ * used for asynchronous callbacks by the server. <br /><br />
+ *
+ * As all system server binder calls must be {@code oneway}, this means all invocations
+ * into {@link com.google.android.startop.iorap.IIorap} are non-blocking. The request ID
+ * exists to associate all calls with their respective callbacks in
+ * {@link com.google.android.startop.iorap.ITaskListener}.
+ *
+ * @see com.google.android.startop.iorap.IIorap
+ *
+ * @hide
+ */
+public class RequestId implements Parcelable {
+
+ public final long requestId;
+
+ private static Object mLock = new Object();
+ private static long mNextRequestId = 0;
+
+ /**
+ * Create a monotonically increasing request ID.<br /><br />
+ *
+ * It is invalid to re-use the same request ID for multiple method calls on
+ * {@link com.google.android.startop.iorap.IIorap}; a new request ID must be created
+ * each time.
+ */
+ @NonNull public static RequestId nextValueForSequence() {
+ long currentRequestId;
+ synchronized (mLock) {
+ currentRequestId = mNextRequestId;
+ ++mNextRequestId;
+ }
+ return new RequestId(currentRequestId);
+ }
+
+ private RequestId(long requestId) {
+ this.requestId = requestId;
+
+ checkConstructorArguments();
+ }
+
+ private void checkConstructorArguments() {
+ if (requestId < 0) {
+ throw new IllegalArgumentException("request id must be non-negative");
+ }
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{requestId: %ld}", requestId);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ } else if (other instanceof RequestId) {
+ return equals((RequestId) other);
+ }
+ return false;
+ }
+
+ private boolean equals(RequestId other) {
+ return requestId == other.requestId;
+ }
+
+
+ //<editor-fold desc="Binder boilerplate">
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeLong(requestId);
+ }
+
+ private RequestId(Parcel in) {
+ requestId = in.readLong();
+
+ checkConstructorArguments();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<RequestId> CREATOR
+ = new Parcelable.Creator<RequestId>() {
+ public RequestId createFromParcel(Parcel in) {
+ return new RequestId(in);
+ }
+
+ public RequestId[] newArray(int size) {
+ return new RequestId[size];
+ }
+ };
+ //</editor-fold>
+}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/SystemServiceEvent.java b/startop/iorap/src/com/google/android/startop/iorap/SystemServiceEvent.java
new file mode 100644
index 0000000..75d47f9
--- /dev/null
+++ b/startop/iorap/src/com/google/android/startop/iorap/SystemServiceEvent.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 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 com.google.android.startop.iorap;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Forward system service events to iorapd.
+ *
+ * @see com.android.server.SystemService
+ *
+ * @hide
+ */
+public class SystemServiceEvent implements Parcelable {
+
+ /** @see com.android.server.SystemService#onBootPhase */
+ public static final int TYPE_BOOT_PHASE = 0;
+ /** @see com.android.server.SystemService#onStart */
+ public static final int TYPE_START = 1;
+ private static final int TYPE_MAX = TYPE_START;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = { "TYPE_" }, value = {
+ TYPE_BOOT_PHASE,
+ TYPE_START,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Type {}
+
+ @Type public final int type;
+
+ // TODO: do we want to pass the exact build phase enum?
+
+ public SystemServiceEvent(@Type int type) {
+ this.type = type;
+ checkConstructorArguments();
+ }
+
+ private void checkConstructorArguments() {
+ CheckHelpers.checkTypeInRange(type, TYPE_MAX);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{type: %d}", type);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ } else if (other instanceof SystemServiceEvent) {
+ return equals((SystemServiceEvent) other);
+ }
+ return false;
+ }
+
+ private boolean equals(SystemServiceEvent other) {
+ return type == other.type;
+ }
+
+ //<editor-fold desc="Binder boilerplate">
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(type);
+ }
+
+ private SystemServiceEvent(Parcel in) {
+ this.type = in.readInt();
+ checkConstructorArguments();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<SystemServiceEvent> CREATOR
+ = new Parcelable.Creator<SystemServiceEvent>() {
+ public SystemServiceEvent createFromParcel(Parcel in) {
+ return new SystemServiceEvent(in);
+ }
+
+ public SystemServiceEvent[] newArray(int size) {
+ return new SystemServiceEvent[size];
+ }
+ };
+ //</editor-fold>
+}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java b/startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java
new file mode 100644
index 0000000..b77c03c
--- /dev/null
+++ b/startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 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 com.google.android.startop.iorap;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Forward user events to iorapd.<br /><br />
+ *
+ * Knowledge of the logged-in user is reserved to be used to set-up appropriate policies
+ * by iorapd (e.g. to handle user default pinned applications changing).
+ *
+ * @see com.android.server.SystemService
+ *
+ * @hide
+ */
+public class SystemServiceUserEvent implements Parcelable {
+
+ /** @see com.android.server.SystemService#onStartUser */
+ public static final int TYPE_START_USER = 0;
+ /** @see com.android.server.SystemService#onUnlockUser */
+ public static final int TYPE_UNLOCK_USER = 1;
+ /** @see com.android.server.SystemService#onSwitchUser*/
+ public static final int TYPE_SWITCH_USER = 2;
+ /** @see com.android.server.SystemService#onStopUser */
+ public static final int TYPE_STOP_USER = 3;
+ /** @see com.android.server.SystemService#onCleanupUser */
+ public static final int TYPE_CLEANUP_USER = 4;
+ private static final int TYPE_MAX = TYPE_CLEANUP_USER;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = { "TYPE_" }, value = {
+ TYPE_START_USER,
+ TYPE_UNLOCK_USER,
+ TYPE_SWITCH_USER,
+ TYPE_STOP_USER,
+ TYPE_CLEANUP_USER,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Type {}
+
+ @Type public final int type;
+ public final int userHandle;
+
+ public SystemServiceUserEvent(@Type int type, int userHandle) {
+ this.type = type;
+ this.userHandle = userHandle;
+ checkConstructorArguments();
+ }
+
+ private void checkConstructorArguments() {
+ CheckHelpers.checkTypeInRange(type, TYPE_MAX);
+ if (userHandle < 0) {
+ throw new IllegalArgumentException("userHandle must be non-negative");
+ }
+ }
+
+ @Override
+ public String toString() {
+ return String.format("{type: %d, userHandle: %d}", type, userHandle);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ } else if (other instanceof SystemServiceUserEvent) {
+ return equals((SystemServiceUserEvent) other);
+ }
+ return false;
+ }
+
+ private boolean equals(SystemServiceUserEvent other) {
+ return type == other.type &&
+ userHandle == other.userHandle;
+ }
+
+ //<editor-fold desc="Binder boilerplate">
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(type);
+ out.writeInt(userHandle);
+ }
+
+ private SystemServiceUserEvent(Parcel in) {
+ this.type = in.readInt();
+ this.userHandle = in.readInt();
+ checkConstructorArguments();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<SystemServiceUserEvent> CREATOR
+ = new Parcelable.Creator<SystemServiceUserEvent>() {
+ public SystemServiceUserEvent createFromParcel(Parcel in) {
+ return new SystemServiceUserEvent(in);
+ }
+
+ public SystemServiceUserEvent[] newArray(int size) {
+ return new SystemServiceUserEvent[size];
+ }
+ };
+ //</editor-fold>
+}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/TaskResult.java b/startop/iorap/src/com/google/android/startop/iorap/TaskResult.java
new file mode 100644
index 0000000..b5fd6d8
--- /dev/null
+++ b/startop/iorap/src/com/google/android/startop/iorap/TaskResult.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 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 com.google.android.startop.iorap;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Result data accompanying a request for {@link com.google.android.startop.iorap.ITaskListener}
+ * callbacks.<br /><br />
+ *
+ * Following {@link com.google.android.startop.iorap.IIorap} method invocation,
+ * iorapd will issue in-order callbacks for that corresponding {@link RequestId}.<br /><br />
+ *
+ * State transitions are as follows: <br /><br />
+ *
+ * <pre>
+ * ┌─────────────────────────────┐
+ * │ ▼
+ * ┌───────┐ ┌─────────┐ ╔═══════════╗
+ * ──▶ │ BEGAN │ ──▶ │ ONGOING │ ──▶ ║ COMPLETED ║
+ * └───────┘ └─────────┘ ╚═══════════╝
+ * │ │
+ * │ │
+ * ▼ │
+ * ╔═══════╗ │
+ * ──▶ ║ ERROR ║ ◀─────┘
+ * ╚═══════╝
+ *
+ * </pre> <!-- system/iorap/docs/binder/TaskResult.dot -->
+ *
+ * @hide
+ */
+public class TaskResult implements Parcelable {
+
+ public static final int STATE_BEGAN = 0;
+ public static final int STATE_ONGOING = 1;
+ public static final int STATE_COMPLETED = 2;
+ public static final int STATE_ERROR = 3;
+ private static final int STATE_MAX = STATE_ERROR;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = { "STATE_" }, value = {
+ STATE_BEGAN,
+ STATE_ONGOING,
+ STATE_COMPLETED,
+ STATE_ERROR,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface State {}
+
+ @State public final int state;
+
+ @Override
+ public String toString() {
+ return String.format("{state: %d}", state);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ } else if (other instanceof TaskResult) {
+ return equals((TaskResult) other);
+ }
+ return false;
+ }
+
+ private boolean equals(TaskResult other) {
+ return state == other.state;
+ }
+
+ public TaskResult(@State int state) {
+ this.state = state;
+
+ checkConstructorArguments();
+ }
+
+ private void checkConstructorArguments() {
+ CheckHelpers.checkStateInRange(state, STATE_MAX);
+ }
+
+ //<editor-fold desc="Binder boilerplate">
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(state);
+ }
+
+ private TaskResult(Parcel in) {
+ state = in.readInt();
+
+ checkConstructorArguments();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<TaskResult> CREATOR
+ = new Parcelable.Creator<TaskResult>() {
+ public TaskResult createFromParcel(Parcel in) {
+ return new TaskResult(in);
+ }
+
+ public TaskResult[] newArray(int size) {
+ return new TaskResult[size];
+ }
+ };
+ //</editor-fold>
+}
diff --git a/startop/iorap/tests/Android.bp b/startop/iorap/tests/Android.bp
new file mode 100644
index 0000000..7605784
--- /dev/null
+++ b/startop/iorap/tests/Android.bp
@@ -0,0 +1,40 @@
+// Copyright (C) 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.
+
+// TODO: once b/80095087 is fixed, rewrite this back to android_test
+java_library {
+ name: "libiorap-java-test-lib",
+ srcs: ["src/**/*.kt"],
+
+ static_libs: [
+ // non-test dependencies
+ "libiorap-java",
+ // test android dependencies
+ "platform-test-annotations",
+ "android-support-test",
+ // test framework dependencies
+ "mockito-target-inline-minus-junit4",
+ // "mockito-target-minus-junit4",
+ // Mockito also requires JNI (see Android.mk)
+ // and android:debuggable=true (see AndroidManifest.xml)
+ "truth-prebuilt",
+ ],
+
+ // sdk_version: "current",
+ // certificate: "platform",
+
+ libs: ["android.test.base", "android.test.runner"],
+
+ // test_suites: ["device-tests"],
+}
diff --git a/startop/iorap/tests/Android.mk b/startop/iorap/tests/Android.mk
new file mode 100644
index 0000000..1b2aa46
--- /dev/null
+++ b/startop/iorap/tests/Android.mk
@@ -0,0 +1,46 @@
+# Copyright (C) 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.
+
+# android_test does not support JNI libraries
+# TODO: once b/80095087 is fixed, rewrite this back to android_test
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_JACK_FLAGS := --multi-dex native
+LOCAL_DX_FLAGS := --multi-dex
+
+LOCAL_PACKAGE_NAME := libiorap-java-tests
+LOCAL_COMPATIBILITY_SUITE := device-tests
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ libiorap-java-test-lib
+
+LOCAL_MULTILIB := both
+
+LOCAL_JNI_SHARED_LIBRARIES := \
+ libdexmakerjvmtiagent \
+ libstaticjvmtiagent \
+ libmultiplejvmtiagentsinterferenceagent
+
+LOCAL_JAVA_LIBRARIES := \
+ android.test.base \
+ android.test.runner
+
+# Use private APIs
+LOCAL_CERTIFICATE := platform
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+include $(BUILD_PACKAGE)
diff --git a/startop/iorap/tests/AndroidManifest.xml b/startop/iorap/tests/AndroidManifest.xml
new file mode 100644
index 0000000..99f4add
--- /dev/null
+++ b/startop/iorap/tests/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 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.
+-->
+<!--suppress AndroidUnknownAttribute -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.google.android.startop.iorap.tests"
+ android:sharedUserId="com.google.android.startop.iorap.tests"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <!--suppress AndroidDomInspection -->
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.google.android.startop.iorap.tests" />
+
+ <!--
+ 'debuggable=true' is required to properly load mockito jvmti dependencies,
+ otherwise it gives the following error at runtime:
+
+ Openjdkjvmti plugin was loaded on a non-debuggable Runtime.
+ Plugin was loaded too late to change runtime state to DEBUGGABLE. -->
+ <application android:debuggable="true">
+ <uses-library android:name="android.test.runner" />
+ </application>
+</manifest>
diff --git a/startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt b/startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt
new file mode 100644
index 0000000..4ba44a9
--- /dev/null
+++ b/startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 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 com.google.android.startop.iorap
+
+import android.net.Uri
+import android.os.ServiceManager
+import android.support.test.filters.MediumTest
+import org.junit.Test
+import org.junit.Ignore
+import org.mockito.Mockito.*
+
+// @Ignore("Test is disabled until iorapd is added to init and there's selinux policies for it")
+@MediumTest
+class IIorapIntegrationTest {
+ /**
+ * @throws ServiceManager.ServiceNotFoundException if iorapd service could not be found
+ */
+ private val iorapService : IIorap by lazy {
+ // TODO: connect to 'iorapd.stub' which doesn't actually do any work other than reply.
+ IIorap.Stub.asInterface(ServiceManager.getServiceOrThrow("iorapd"))
+
+ // Use 'adb shell setenforce 0' otherwise this whole test fails,
+ // because the servicemanager is not allowed to hand out the binder token for iorapd.
+
+ // TODO: implement the selinux policies for iorapd.
+ }
+
+ // A dummy binder stub implementation is required to use with mockito#spy.
+ // Mockito overrides the methods at runtime and tracks how methods were invoked.
+ open class DummyTaskListener : ITaskListener.Stub() {
+ // Note: make parameters nullable to avoid the kotlin IllegalStateExceptions
+ // from using the mockito matchers (eq, argThat, etc).
+ override fun onProgress(requestId: RequestId?, result: TaskResult?) {
+ }
+
+ override fun onComplete(requestId: RequestId?, result: TaskResult?) {
+ }
+ }
+
+ private fun testAnyMethod(func : (RequestId) -> Unit) {
+ val taskListener = spy(DummyTaskListener())!!
+
+ try {
+ iorapService.setTaskListener(taskListener)
+ // Note: Binder guarantees total order for oneway messages sent to the same binder
+ // interface, so we don't need any additional blocking here before sending later calls.
+
+ // Every new method call should have a unique request id.
+ val requestId = RequestId.nextValueForSequence()!!
+
+ // Apply the specific function under test.
+ func(requestId)
+
+ // Typical mockito behavior is to allow any-order callbacks, but we want to test order.
+ val inOrder = inOrder(taskListener)
+
+ // The "stub" behavior of iorapd is that every request immediately gets a response of
+ // BEGAN,ONGOING,COMPLETED
+ inOrder.verify(taskListener, timeout(100)).
+ onProgress(eq(requestId), argThat { it!!.state == TaskResult.STATE_BEGAN })
+ inOrder.verify(taskListener, timeout(100)).
+ onProgress(eq(requestId), argThat { it!!.state == TaskResult.STATE_ONGOING })
+ inOrder.verify(taskListener, timeout(100)).
+ onComplete(eq(requestId), argThat { it!!.state == TaskResult.STATE_COMPLETED })
+ inOrder.verifyNoMoreInteractions()
+
+ } finally {
+ iorapService.setTaskListener(null)
+ }
+ }
+
+ @Test
+ fun testOnPackageEvent() {
+ testAnyMethod { requestId : RequestId ->
+ iorapService.onPackageEvent(requestId,
+ PackageEvent.createReplaced(
+ Uri.parse("https://www.google.com"), "com.fake.package"))
+ }
+ }
+
+ @Test
+ fun testOnAppIntentEvent() {
+ testAnyMethod { requestId : RequestId ->
+ iorapService.onAppIntentEvent(requestId, AppIntentEvent.createDefaultIntentChanged(
+ ActivityInfo("dont care", "dont care"),
+ ActivityInfo("dont care 2", "dont care 2")))
+ }
+ }
+
+ @Test
+ fun testOnSystemServiceEvent() {
+ testAnyMethod { requestId : RequestId ->
+ iorapService.onSystemServiceEvent(requestId,
+ SystemServiceEvent(SystemServiceEvent.TYPE_START))
+ }
+ }
+
+ @Test
+ fun testOnSystemServiceUserEvent() {
+ testAnyMethod { requestId : RequestId ->
+ iorapService.onSystemServiceUserEvent(requestId,
+ SystemServiceUserEvent(SystemServiceUserEvent.TYPE_START_USER,0))
+ }
+ }
+}
diff --git a/startop/iorap/tests/src/com/google/android/startop/iorap/ParcelablesTest.kt b/startop/iorap/tests/src/com/google/android/startop/iorap/ParcelablesTest.kt
new file mode 100644
index 0000000..4abbb3e
--- /dev/null
+++ b/startop/iorap/tests/src/com/google/android/startop/iorap/ParcelablesTest.kt
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 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 com.google.android.startop.iorap
+
+import android.net.Uri
+import android.os.Parcel
+import android.os.Parcelable
+import android.support.test.filters.SmallTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import com.google.common.truth.Truth.assertThat
+import org.junit.runners.Parameterized
+
+/**
+ * Basic unit tests to ensure that all of the [Parcelable]s in [com.google.android.startop.iorap]
+ * have a valid-conforming interface implementation.
+ */
+@SmallTest
+@RunWith(Parameterized::class)
+class ParcelablesTest<T : Parcelable>(private val inputData : InputData<T>) {
+ companion object {
+ private val initialRequestId = RequestId.nextValueForSequence()!!
+
+ @JvmStatic
+ @Parameterized.Parameters
+ fun data() = listOf(
+ InputData(
+ newActivityInfo(),
+ newActivityInfo(),
+ ActivityInfo("some package", "some other activity")),
+ InputData(
+ ActivityHintEvent(ActivityHintEvent.TYPE_COMPLETED, newActivityInfo()),
+ ActivityHintEvent(ActivityHintEvent.TYPE_COMPLETED, newActivityInfo()),
+ ActivityHintEvent(ActivityHintEvent.TYPE_POST_COMPLETED,
+ newActivityInfo())),
+ InputData(
+ AppIntentEvent.createDefaultIntentChanged(newActivityInfo(),
+ newActivityInfoOther()),
+ AppIntentEvent.createDefaultIntentChanged(newActivityInfo(),
+ newActivityInfoOther()),
+ AppIntentEvent.createDefaultIntentChanged(newActivityInfoOther(),
+ newActivityInfo())),
+ InputData(
+ PackageEvent.createReplaced(newUri(), "some package"),
+ PackageEvent.createReplaced(newUri(), "some package"),
+ PackageEvent.createReplaced(newUri(), "some other package")
+ ),
+ InputData(initialRequestId, cloneRequestId(initialRequestId),
+ RequestId.nextValueForSequence()),
+ InputData(
+ SystemServiceEvent(SystemServiceEvent.TYPE_BOOT_PHASE),
+ SystemServiceEvent(SystemServiceEvent.TYPE_BOOT_PHASE),
+ SystemServiceEvent(SystemServiceEvent.TYPE_START)),
+ InputData(
+ SystemServiceUserEvent(SystemServiceUserEvent.TYPE_START_USER, 12345),
+ SystemServiceUserEvent(SystemServiceUserEvent.TYPE_START_USER, 12345),
+ SystemServiceUserEvent(SystemServiceUserEvent.TYPE_CLEANUP_USER, 12345)),
+ InputData(
+ TaskResult(TaskResult.STATE_COMPLETED),
+ TaskResult(TaskResult.STATE_COMPLETED),
+ TaskResult(TaskResult.STATE_ONGOING))
+ )
+
+ private fun newActivityInfo() : ActivityInfo {
+ return ActivityInfo("some package", "some activity")
+ }
+
+ private fun newActivityInfoOther() : ActivityInfo {
+ return ActivityInfo("some package 2", "some activity 2")
+ }
+
+ private fun newUri() : Uri {
+ return Uri.parse("https://www.google.com")
+ }
+
+ private fun cloneRequestId(requestId: RequestId) : RequestId {
+ val constructor = requestId::class.java.declaredConstructors[0]
+ constructor.isAccessible = true
+ return constructor.newInstance(requestId.requestId) as RequestId
+ }
+ }
+
+ /**
+ * Test for [Object.equals] implementation.
+ */
+ @Test
+ fun testEquality() {
+ assertThat(inputData.valid).isEqualTo(inputData.valid)
+ assertThat(inputData.valid).isEqualTo(inputData.validCopy)
+ assertThat(inputData.valid).isNotEqualTo(inputData.validOther)
+ }
+
+ /**
+ * Test for [Parcelable] implementation.
+ */
+ @Test
+ fun testParcelRoundTrip() {
+ // calling writeToParcel and then T::CREATOR.createFromParcel would return the same data.
+ val assertParcels = { it : T, data : InputData<T> ->
+ val parcel = Parcel.obtain()
+ it.writeToParcel(parcel, 0)
+ parcel.setDataPosition(0) // future reads will see all previous writes.
+ assertThat(it).isEqualTo(data.createFromParcel(parcel))
+ parcel.recycle()
+ }
+
+ assertParcels(inputData.valid, inputData)
+ assertParcels(inputData.validCopy, inputData)
+ assertParcels(inputData.validOther, inputData)
+ }
+
+ data class InputData<T : Parcelable>(val valid : T, val validCopy : T, val validOther : T) {
+ val kls = valid.javaClass
+ init {
+ assertThat(valid).isNotSameAs(validCopy)
+ // Don't use isInstanceOf because of phantom warnings in intellij about Class!
+ assertThat(validCopy.javaClass).isEqualTo(valid.javaClass)
+ assertThat(validOther.javaClass).isEqualTo(valid.javaClass)
+ }
+
+ fun createFromParcel(parcel : Parcel) : T {
+ val field = kls.getDeclaredField("CREATOR")
+ val creator = field.get(null) as Parcelable.Creator<T>
+
+ return creator.createFromParcel(parcel)
+ }
+ }
+}
diff --git a/startop/tools/view_compiler/Android.bp b/startop/tools/view_compiler/Android.bp
new file mode 100644
index 0000000..c3e9184
--- /dev/null
+++ b/startop/tools/view_compiler/Android.bp
@@ -0,0 +1,49 @@
+//
+// Copyright (C) 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.
+//
+
+cc_library_host_static {
+ name: "libviewcompiler",
+ srcs: [
+ "java_lang_builder.cc",
+ "util.cc",
+ ],
+ static_libs: [
+ "libbase"
+ ]
+}
+
+cc_binary_host {
+ name: "viewcompiler",
+ srcs: [
+ "main.cc",
+ ],
+ static_libs: [
+ "libbase",
+ "libtinyxml2",
+ "libgflags",
+ "libviewcompiler",
+ ],
+}
+
+cc_test_host {
+ name: "view-compiler-tests",
+ srcs: [
+ "util_test.cc",
+ ],
+ static_libs: [
+ "libviewcompiler",
+ ]
+}
diff --git a/startop/tools/view_compiler/README.md b/startop/tools/view_compiler/README.md
new file mode 100644
index 0000000..5659501
--- /dev/null
+++ b/startop/tools/view_compiler/README.md
@@ -0,0 +1,25 @@
+# View Compiler
+
+This directory contains an experimental compiler for layout files.
+
+It will take a layout XML file and produce a CompiledLayout.java file with a
+specialized layout inflation function.
+
+To use it, let's assume you had a layout in `my_layout.xml` and your app was in
+the Java language package `com.example.myapp`. Run the following command:
+
+ viewcompiler my_layout.xml --package com.example.myapp --out CompiledView.java
+
+This will produce a `CompiledView.java`, which can then be compiled into your
+Android app. Then to use it, in places where you would have inflated
+`R.layouts.my_layout`, instead call `CompiledView.inflate`.
+
+Precompiling views like this generally improves the time needed to inflate them.
+
+This tool is still in its early stages and has a number of limitations.
+* Currently only one layout can be compiled at a time.
+* `merge` and `include` nodes are not supported.
+* View compilation is a manual process that requires code changes in the
+ application.
+* This only works for apps that do not use a custom layout inflater.
+* Other limitations yet to be discovered.
diff --git a/startop/tools/view_compiler/TEST_MAPPING b/startop/tools/view_compiler/TEST_MAPPING
new file mode 100644
index 0000000..cc4b17a
--- /dev/null
+++ b/startop/tools/view_compiler/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "view-compiler-tests"
+ }
+ ]
+}
diff --git a/startop/tools/view_compiler/java_lang_builder.cc b/startop/tools/view_compiler/java_lang_builder.cc
new file mode 100644
index 0000000..0b8754f
--- /dev/null
+++ b/startop/tools/view_compiler/java_lang_builder.cc
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "java_lang_builder.h"
+
+#include "android-base/stringprintf.h"
+
+using android::base::StringPrintf;
+using std::string;
+
+void JavaLangViewBuilder::Start() const {
+ out_ << StringPrintf("package %s;\n", package_.c_str())
+ << "import android.content.Context;\n"
+ "import android.content.res.Resources;\n"
+ "import android.content.res.XmlResourceParser;\n"
+ "import android.util.AttributeSet;\n"
+ "import android.util.Xml;\n"
+ "import android.view.*;\n"
+ "import android.widget.*;\n"
+ "\n"
+ "public final class CompiledView {\n"
+ "\n"
+ "static <T extends View> T createView(Context context, AttributeSet attrs, View parent, "
+ "String name, LayoutInflater.Factory factory, LayoutInflater.Factory2 factory2) {"
+ "\n"
+ " if (factory2 != null) {\n"
+ " return (T)factory2.onCreateView(parent, name, context, attrs);\n"
+ " } else if (factory != null) {\n"
+ " return (T)factory.onCreateView(name, context, attrs);\n"
+ " }\n"
+ // TODO: find a way to call the private factory
+ " return null;\n"
+ "}\n"
+ "\n"
+ " public static View inflate(Context context) {\n"
+ " try {\n"
+ " LayoutInflater inflater = LayoutInflater.from(context);\n"
+ " LayoutInflater.Factory factory = inflater.getFactory();\n"
+ " LayoutInflater.Factory2 factory2 = inflater.getFactory2();\n"
+ " Resources res = context.getResources();\n"
+ << StringPrintf(" XmlResourceParser xml = res.getLayout(%s.R.layout.%s);\n",
+ package_.c_str(),
+ layout_name_.c_str())
+ << " AttributeSet attrs = Xml.asAttributeSet(xml);\n"
+ // The Java-language XmlPullParser needs a call to next to find the start document tag.
+ " xml.next(); // start document\n";
+}
+
+void JavaLangViewBuilder::Finish() const {
+ out_ << " } catch (Exception e) {\n"
+ " return null;\n"
+ " }\n" // end try
+ " }\n" // end inflate
+ "}\n"; // end CompiledView
+}
+
+void JavaLangViewBuilder::StartView(const string& class_name) {
+ const string view_var = MakeVar("view");
+ const string layout_var = MakeVar("layout");
+ std::string parent = "null";
+ if (!view_stack_.empty()) {
+ const StackEntry& parent_entry = view_stack_.back();
+ parent = parent_entry.view_var;
+ }
+ out_ << " xml.next(); // <" << class_name << ">\n"
+ << StringPrintf(" %s %s = createView(context, attrs, %s, \"%s\", factory, factory2);\n",
+ class_name.c_str(),
+ view_var.c_str(),
+ parent.c_str(),
+ class_name.c_str())
+ << StringPrintf(" if (%s == null) %s = new %s(context, attrs);\n",
+ view_var.c_str(),
+ view_var.c_str(),
+ class_name.c_str());
+ if (!view_stack_.empty()) {
+ out_ << StringPrintf(" ViewGroup.LayoutParams %s = %s.generateLayoutParams(attrs);\n",
+ layout_var.c_str(),
+ parent.c_str());
+ }
+ view_stack_.push_back({class_name, view_var, layout_var});
+}
+
+void JavaLangViewBuilder::FinishView() {
+ const StackEntry var = view_stack_.back();
+ view_stack_.pop_back();
+ if (!view_stack_.empty()) {
+ const string& parent = view_stack_.back().view_var;
+ out_ << StringPrintf(" xml.next(); // </%s>\n", var.class_name.c_str())
+ << StringPrintf(" %s.addView(%s, %s);\n",
+ parent.c_str(),
+ var.view_var.c_str(),
+ var.layout_params_var.c_str());
+ } else {
+ out_ << StringPrintf(" return %s;\n", var.view_var.c_str());
+ }
+}
+
+const std::string JavaLangViewBuilder::MakeVar(std::string prefix) {
+ std::stringstream v;
+ v << prefix << view_id_++;
+ return v.str();
+}
diff --git a/startop/tools/view_compiler/java_lang_builder.h b/startop/tools/view_compiler/java_lang_builder.h
new file mode 100644
index 0000000..c8d20b2
--- /dev/null
+++ b/startop/tools/view_compiler/java_lang_builder.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 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.
+ */
+#ifndef JAVA_LANG_BUILDER_H_
+#define JAVA_LANG_BUILDER_H_
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+// Build Java language code to instantiate views.
+//
+// This has a very small interface to make it easier to generate additional
+// backends, such as a direct-to-DEX version.
+class JavaLangViewBuilder {
+ public:
+ JavaLangViewBuilder(std::string package, std::string layout_name, std::ostream& out = std::cout)
+ : package_(package), layout_name_(layout_name), out_(out) {}
+
+ // Begin generating a class. Adds the package boilerplate, etc.
+ void Start() const;
+ // Finish generating a class, closing off any open curly braces, etc.
+ void Finish() const;
+
+ // Begin creating a view (i.e. process the opening tag)
+ void StartView(const std::string& class_name);
+ // Finish a view, after all of its child nodes have been processed.
+ void FinishView();
+
+ private:
+ const std::string MakeVar(std::string prefix);
+
+ std::string const package_;
+ std::string const layout_name_;
+
+ std::ostream& out_;
+
+ size_t view_id_ = 0;
+
+ struct StackEntry {
+ // The class name for this view object
+ const std::string class_name;
+
+ // The variable name that is holding the view object
+ const std::string view_var;
+
+ // The variable name that holds the object's layout parameters
+ const std::string layout_params_var;
+ };
+ std::vector<StackEntry> view_stack_;
+};
+
+#endif // JAVA_LANG_BUILDER_H_
diff --git a/startop/tools/view_compiler/main.cc b/startop/tools/view_compiler/main.cc
new file mode 100644
index 0000000..0ad7e24
--- /dev/null
+++ b/startop/tools/view_compiler/main.cc
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "gflags/gflags.h"
+
+#include "java_lang_builder.h"
+#include "util.h"
+
+#include "tinyxml2.h"
+
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+using namespace tinyxml2;
+using std::string;
+
+constexpr char kStdoutFilename[]{"stdout"};
+
+DEFINE_string(package, "", "The package name for the generated class (required)");
+DEFINE_string(out, kStdoutFilename, "Where to write the generated class");
+
+namespace {
+class ViewCompilerXmlVisitor : public XMLVisitor {
+ public:
+ ViewCompilerXmlVisitor(JavaLangViewBuilder* builder) : builder_(builder) {}
+
+ bool VisitEnter(const XMLDocument& /*doc*/) override {
+ builder_->Start();
+ return true;
+ }
+
+ bool VisitExit(const XMLDocument& /*doc*/) override {
+ builder_->Finish();
+ return true;
+ }
+
+ bool VisitEnter(const XMLElement& element, const XMLAttribute* /*firstAttribute*/) override {
+ builder_->StartView(element.Name());
+ return true;
+ }
+
+ bool VisitExit(const XMLElement& /*element*/) override {
+ builder_->FinishView();
+ return true;
+ }
+
+ private:
+ JavaLangViewBuilder* builder_;
+};
+} // end namespace
+
+int main(int argc, char** argv) {
+ constexpr size_t kProgramName = 0;
+ constexpr size_t kFileNameParam = 1;
+ constexpr size_t kNumRequiredArgs = 2;
+
+ gflags::SetUsageMessage(
+ "Compile XML layout files into equivalent Java language code\n"
+ "\n"
+ " example usage: viewcompiler layout.xml --package com.example.androidapp");
+ gflags::ParseCommandLineFlags(&argc, &argv, /*remove_flags*/ true);
+
+ gflags::CommandLineFlagInfo cmd = gflags::GetCommandLineFlagInfoOrDie("package");
+ if (argc != kNumRequiredArgs || cmd.is_default) {
+ gflags::ShowUsageWithFlags(argv[kProgramName]);
+ return 1;
+ }
+
+ const char* const filename = argv[kFileNameParam];
+ const string layout_name = FindLayoutNameFromFilename(filename);
+
+ // We want to generate Java language code to inflate exactly this layout. This means
+ // generating code to walk the resource XML too.
+
+ XMLDocument xml;
+ xml.LoadFile(filename);
+
+ std::ofstream outfile;
+ if (FLAGS_out != kStdoutFilename) {
+ outfile.open(FLAGS_out);
+ }
+ JavaLangViewBuilder builder{
+ FLAGS_package, layout_name, FLAGS_out == kStdoutFilename ? std::cout : outfile};
+
+ ViewCompilerXmlVisitor visitor{&builder};
+ xml.Accept(&visitor);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/startop/tools/view_compiler/util.cc b/startop/tools/view_compiler/util.cc
new file mode 100644
index 0000000..69df41d
--- /dev/null
+++ b/startop/tools/view_compiler/util.cc
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "util.h"
+
+using std::string;
+
+// TODO: see if we can borrow this from somewhere else, like aapt2.
+string FindLayoutNameFromFilename(const string& filename) {
+ size_t start = filename.rfind("/");
+ if (start == string::npos) {
+ start = 0;
+ } else {
+ start++; // advance past '/' character
+ }
+ size_t end = filename.find(".", start);
+
+ return filename.substr(start, end - start);
+}
diff --git a/startop/tools/view_compiler/util.h b/startop/tools/view_compiler/util.h
new file mode 100644
index 0000000..03e0939
--- /dev/null
+++ b/startop/tools/view_compiler/util.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 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.
+ */
+#ifndef UTIL_H_
+#define UTIL_H_
+
+#include <string>
+
+std::string FindLayoutNameFromFilename(const std::string& filename);
+
+#endif // UTIL_H_
diff --git a/startop/tools/view_compiler/util_test.cc b/startop/tools/view_compiler/util_test.cc
new file mode 100644
index 0000000..d1540d3
--- /dev/null
+++ b/startop/tools/view_compiler/util_test.cc
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "util.h"
+
+#include "gtest/gtest.h"
+
+using std::string;
+
+TEST(UtilTest, FindLayoutNameFromFilename) {
+ EXPECT_EQ("bar", ::FindLayoutNameFromFilename("foo/bar.xml"));
+ EXPECT_EQ("bar", ::FindLayoutNameFromFilename("bar.xml"));
+ EXPECT_EQ("bar", ::FindLayoutNameFromFilename("./foo/bar.xml"));
+ EXPECT_EQ("bar", ::FindLayoutNameFromFilename("/foo/bar.xml"));
+}
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 096cf37d..08bc9bc 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -141,6 +141,8 @@
* The caller must specify the {@link #EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE} to indicate to
* Telecom which {@link PhoneAccountHandle} the {@link Call} should be handed over to.
* @hide
+ * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+ * APIs instead.
*/
public static final String EVENT_REQUEST_HANDOVER =
"android.telecom.event.REQUEST_HANDOVER";
@@ -149,6 +151,8 @@
* Extra key used with the {@link #EVENT_REQUEST_HANDOVER} call event. Specifies the
* {@link PhoneAccountHandle} to which a call should be handed over to.
* @hide
+ * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+ * APIs instead.
*/
public static final String EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE =
"android.telecom.extra.HANDOVER_PHONE_ACCOUNT_HANDLE";
@@ -161,6 +165,8 @@
* {@link VideoProfile#STATE_BIDIRECTIONAL}, {@link VideoProfile#STATE_RX_ENABLED}, and
* {@link VideoProfile#STATE_TX_ENABLED}.
* @hide
+ * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+ * APIs instead.
*/
public static final String EXTRA_HANDOVER_VIDEO_STATE =
"android.telecom.extra.HANDOVER_VIDEO_STATE";
@@ -176,6 +182,8 @@
* {@link ConnectionService#onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}
* is called to initate the handover.
* @hide
+ * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+ * APIs instead.
*/
public static final String EXTRA_HANDOVER_EXTRAS = "android.telecom.extra.HANDOVER_EXTRAS";
@@ -186,6 +194,8 @@
* <p>
* A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
* @hide
+ * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+ * APIs instead.
*/
public static final String EVENT_HANDOVER_COMPLETE =
"android.telecom.event.HANDOVER_COMPLETE";
@@ -198,6 +208,8 @@
* <p>
* A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
* @hide
+ * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+ * APIs instead.
*/
public static final String EVENT_HANDOVER_SOURCE_DISCONNECTED =
"android.telecom.event.HANDOVER_SOURCE_DISCONNECTED";
@@ -209,6 +221,8 @@
* <p>
* A handover is initiated with the {@link #EVENT_REQUEST_HANDOVER} call event.
* @hide
+ * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+ * APIs instead.
*/
public static final String EVENT_HANDOVER_FAILED =
"android.telecom.event.HANDOVER_FAILED";
@@ -434,8 +448,15 @@
*/
public static final int PROPERTY_RTT = 0x00000400;
+ /**
+ * Indicates that the call has been identified as the network as an emergency call. This
+ * property may be set for both incoming and outgoing calls which the network identifies as
+ * emergency calls.
+ */
+ public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 0x00000800;
+
//******************************************************************************************
- // Next PROPERTY value: 0x00000800
+ // Next PROPERTY value: 0x00001000
//******************************************************************************************
private final String mTelecomCallId;
@@ -601,6 +622,9 @@
if(hasProperty(properties, PROPERTY_ASSISTED_DIALING_USED)) {
builder.append(" PROPERTY_ASSISTED_DIALING_USED");
}
+ if (hasProperty(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) {
+ builder.append(" PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL");
+ }
builder.append("]");
return builder.toString();
}
diff --git a/telecomm/java/android/telecom/CallRedirectionService.java b/telecomm/java/android/telecom/CallRedirectionService.java
index 9c874bf..b906d0b 100644
--- a/telecomm/java/android/telecom/CallRedirectionService.java
+++ b/telecomm/java/android/telecom/CallRedirectionService.java
@@ -63,6 +63,10 @@
/**
* Telecom calls this method to inform the implemented {@link CallRedirectionService} of
* a new outgoing call which is being placed.
+ *
+ * The implemented {@link CallRedirectionService} can call {@link #placeCallUnmodified()},
+ * {@link #redirectCall(Uri, PhoneAccountHandle)}, and {@link #cancelCall()} only from here.
+ *
* @param handle the phone number dialed by the user
* @param targetPhoneAccount the {@link PhoneAccountHandle} on which the call will be placed.
*/
@@ -72,6 +76,9 @@
* The implemented {@link CallRedirectionService} calls this method to response a request
* received via {@link #onPlaceCall(Uri, PhoneAccountHandle)} to inform Telecom that no changes
* are required to the outgoing call, and that the call should be placed as-is.
+ *
+ * This can only be called from implemented {@link #onPlaceCall(Uri, PhoneAccountHandle)}.
+ *
*/
public final void placeCallUnmodified() {
try {
@@ -84,6 +91,9 @@
* The implemented {@link CallRedirectionService} calls this method to response a request
* received via {@link #onPlaceCall(Uri, PhoneAccountHandle)} to inform Telecom that changes
* are required to the phone number or/and {@link PhoneAccountHandle} for the outgoing call.
+ *
+ * This can only be called from implemented {@link #onPlaceCall(Uri, PhoneAccountHandle)}.
+ *
* @param handle the new phone number to dial
* @param targetPhoneAccount the {@link PhoneAccountHandle} to use when placing the call.
* If {@code null}, no change will be made to the
@@ -100,6 +110,9 @@
* The implemented {@link CallRedirectionService} calls this method to response a request
* received via {@link #onPlaceCall(Uri, PhoneAccountHandle)} to inform Telecom that an outgoing
* call should be canceled entirely.
+ *
+ * This can only be called from implemented {@link #onPlaceCall(Uri, PhoneAccountHandle)}.
+ *
*/
public final void cancelCall() {
try {
@@ -144,7 +157,6 @@
@Override
public void placeCall(ICallRedirectionAdapter adapter, Uri handle,
PhoneAccountHandle targetPhoneAccount) {
- Log.v(this, "placeCall");
SomeArgs args = SomeArgs.obtain();
args.arg1 = adapter;
args.arg2 = handle;
@@ -154,14 +166,12 @@
}
@Override
- public IBinder onBind(Intent intent) {
- Log.v(this, "onBind");
+ public final IBinder onBind(Intent intent) {
return new CallRedirectionBinder();
}
@Override
- public boolean onUnbind(Intent intent) {
- Log.v(this, "onUnbind");
+ public final boolean onUnbind(Intent intent) {
return false;
}
}
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 024bd30..a39e885 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -22,6 +22,8 @@
import android.os.Bundle;
import android.os.SystemClock;
import android.telecom.Connection.VideoProvider;
+import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
import android.util.ArraySet;
import java.util.ArrayList;
@@ -573,6 +575,20 @@
}
/**
+ * Updates RIL voice radio technology used for current conference after its creation.
+ *
+ * @hide
+ */
+ public void updateCallRadioTechAfterCreation() {
+ final Connection primaryConnection = getPrimaryConnection();
+ if (primaryConnection != null) {
+ setCallRadioTech(primaryConnection.getCallRadioTech());
+ } else {
+ Log.w(this, "No primary connection found while updateCallRadioTechAfterCreation");
+ }
+ }
+
+ /**
* @hide
* @deprecated Use {@link #setConnectionTime}.
*/
@@ -652,6 +668,37 @@
}
/**
+ * Sets RIL voice radio technology used for current conference.
+ *
+ * @param vrat the RIL voice radio technology used for current conference,
+ * see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
+ *
+ * @hide
+ */
+ public final void setCallRadioTech(@ServiceState.RilRadioTechnology int vrat) {
+ putExtra(TelecomManager.EXTRA_CALL_NETWORK_TYPE,
+ ServiceState.rilRadioTechnologyToNetworkType(vrat));
+ }
+
+ /**
+ * Returns RIL voice radio technology used for current conference.
+ *
+ * @return the RIL voice radio technology used for current conference,
+ * see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
+ *
+ * @hide
+ */
+ public final @ServiceState.RilRadioTechnology int getCallRadioTech() {
+ int voiceNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ Bundle extras = getExtras();
+ if (extras != null) {
+ voiceNetworkType = extras.getInt(TelecomManager.EXTRA_CALL_NETWORK_TYPE,
+ TelephonyManager.NETWORK_TYPE_UNKNOWN);
+ }
+ return ServiceState.networkTypeToRilRadioTechnology(voiceNetworkType);
+ }
+
+ /**
* Inform this Conference that the state of its audio output has been changed externally.
*
* @param state The new audio state.
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 5d5b15d..ee1ca5f 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -38,6 +38,8 @@
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
import android.util.ArraySet;
import android.view.Surface;
@@ -411,6 +413,13 @@
*/
public static final int PROPERTY_ASSISTED_DIALING_USED = 1 << 9;
+ /**
+ * Set by the framework to indicate that the network has identified a Connection as an emergency
+ * call.
+ * @hide
+ */
+ public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 1 << 10;
+
//**********************************************************************************************
// Next PROPERTY value: 1<<10
//**********************************************************************************************
@@ -584,6 +593,8 @@
* {@link Call#EVENT_REQUEST_HANDOVER} that the handover from this {@link Connection} has
* successfully completed.
* @hide
+ * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+ * APIs instead.
*/
public static final String EVENT_HANDOVER_COMPLETE =
"android.telecom.event.HANDOVER_COMPLETE";
@@ -593,6 +604,8 @@
* {@link Call#EVENT_REQUEST_HANDOVER} that the handover from this {@link Connection} has failed
* to complete.
* @hide
+ * @deprecated Use {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} and its associated
+ * APIs instead.
*/
public static final String EVENT_HANDOVER_FAILED =
"android.telecom.event.HANDOVER_FAILED";
@@ -800,6 +813,10 @@
builder.append(isLong ? " PROPERTY_IS_RTT" : " rtt");
}
+ if (can(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) {
+ builder.append(isLong ? " PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL" : " ecall");
+ }
+
builder.append("]");
return builder.toString();
}
@@ -1879,6 +1896,24 @@
}
/**
+ * Returns RIL voice radio technology used for current connection.
+ *
+ * @return the RIL voice radio technology used for current connection,
+ * see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
+ *
+ * @hide
+ */
+ public final @ServiceState.RilRadioTechnology int getCallRadioTech() {
+ int voiceNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ Bundle extras = getExtras();
+ if (extras != null) {
+ voiceNetworkType = extras.getInt(TelecomManager.EXTRA_CALL_NETWORK_TYPE,
+ TelephonyManager.NETWORK_TYPE_UNKNOWN);
+ }
+ return ServiceState.networkTypeToRilRadioTechnology(voiceNetworkType);
+ }
+
+ /**
* @return The status hints for this connection.
*/
public final StatusHints getStatusHints() {
@@ -2312,6 +2347,26 @@
}
/**
+ * Sets RIL voice radio technology used for current connection.
+ *
+ * @param vrat the RIL Voice Radio Technology used for current connection,
+ * see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
+ *
+ * @hide
+ */
+ public final void setCallRadioTech(@ServiceState.RilRadioTechnology int vrat) {
+ putExtra(TelecomManager.EXTRA_CALL_NETWORK_TYPE,
+ ServiceState.rilRadioTechnologyToNetworkType(vrat));
+ // Propagates the call radio technology to its parent {@link android.telecom.Conference}
+ // This action only covers non-IMS CS conference calls.
+ // For IMS PS call conference call, it can be updated via its host connection
+ // {@link #Listener.onExtrasChanged} event.
+ if (getConference() != null) {
+ getConference().setCallRadioTech(vrat);
+ }
+ }
+
+ /**
* Sets the label and icon status to display in the in-call UI.
*
* @param statusHints The status label and icon to set.
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 4e22823..d33a537 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -317,6 +317,15 @@
"android.telecom.extra.CALL_TECHNOLOGY_TYPE";
/**
+ * Optional extra for communicating the call network technology used by a
+ * {@link android.telecom.Connection} to Telecom and InCallUI.
+ *
+ * @see {@code NETWORK_TYPE_*} in {@link android.telephony.TelephonyManager}.
+ */
+ public static final String EXTRA_CALL_NETWORK_TYPE =
+ "android.telecom.extra.CALL_NETWORK_TYPE";
+
+ /**
* An optional {@link android.content.Intent#ACTION_CALL} intent extra denoting the
* package name of the app specifying an alternative gateway for the call.
* The value is a string.
@@ -1875,6 +1884,43 @@
}
}
+ /**
+ * Determines if there is an ongoing emergency call. This can be either an outgoing emergency
+ * call, as identified by the dialed number, or because a call was identified by the network
+ * as an emergency call.
+ * @return {@code true} if there is an ongoing emergency call, {@code false} otherwise.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public boolean isInEmergencyCall() {
+ try {
+ if (isServiceConnected()) {
+ return getTelecomService().isInEmergencyCall();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException isInEmergencyCall: " + e);
+ return false;
+ }
+ return false;
+ }
+
+ /**
+ * Handles {@link Intent#ACTION_CALL} intents trampolined from UserCallActivity.
+ * @param intent The {@link Intent#ACTION_CALL} intent to handle.
+ * @hide
+ */
+ public void handleCallIntent(Intent intent) {
+ try {
+ if (isServiceConnected()) {
+ getTelecomService().handleCallIntent(intent);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException handleCallIntent: " + e);
+ }
+
+ }
+
private ITelecomService getTelecomService() {
if (mTelecomServiceOverride != null) {
return mTelecomServiceOverride;
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index b4e7d56..df7d683 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -279,4 +279,14 @@
* @see TelecomServiceImpl#acceptHandover
*/
void acceptHandover(in Uri srcAddr, int videoState, in PhoneAccountHandle destAcct);
+
+ /**
+ * @see TelecomServiceImpl#isInEmergencyCall
+ */
+ boolean isInEmergencyCall();
+
+ /**
+ * @see TelecomServiceImpl#handleCallIntent
+ */
+ void handleCallIntent(in Intent intent);
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 9319750..6eaecc6 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -271,6 +271,14 @@
KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
/**
+ * Do only allow auto selection in Advanced Network Settings when in home network.
+ * Manual selection is allowed when in roaming network.
+ * @hide
+ */
+ public static final String
+ KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL = "only_auto_select_in_home_network";
+
+ /**
* Control whether users receive a simplified network settings UI and improved network
* selection.
*/
@@ -1070,6 +1078,16 @@
/**
* Indexes of SPN format strings in wfcSpnFormats and wfcDataSpnFormats.
+ *
+ * <p>Available options are:
+ * <ul>
+ * <li> 0: %s</li>
+ * <li> 1: %s Wi-Fi Calling</li>
+ * <li> 2: WLAN Call</li>
+ * <li> 3: %s WLAN Call</li>
+ * <li> 4: %s Wi-Fi</li>
+ * <li> 5: WiFi Calling | %s</li>
+ * <li> 6: %s VoWifi</li>
* @hide
*/
public static final String KEY_WFC_SPN_FORMAT_IDX_INT = "wfc_spn_format_idx_int";
@@ -1077,6 +1095,15 @@
public static final String KEY_WFC_DATA_SPN_FORMAT_IDX_INT = "wfc_data_spn_format_idx_int";
/**
+ * Use root locale when reading wfcSpnFormats.
+ *
+ * If true, then the root locale will always be used when reading wfcSpnFormats. This means the
+ * non localized version of wfcSpnFormats will be used.
+ * @hide
+ */
+ public static final String KEY_WFC_SPN_USE_ROOT_LOCALE = "wfc_spn_use_root_locale";
+
+ /**
* The Component Name of the activity that can setup the emergency addrees for WiFi Calling
* as per carrier requirement.
* @hide
@@ -1606,11 +1633,21 @@
* When {@code false}, use default title for Enhanced 4G LTE Mode settings.
* When {@code true}, use the variant.
* @hide
+ * @deprecated use {@link #KEY_ENHANCED_4G_LTE_TITLE_VARIANT_INT}.
*/
+ @Deprecated
public static final String KEY_ENHANCED_4G_LTE_TITLE_VARIANT_BOOL =
"enhanced_4g_lte_title_variant_bool";
/**
+ * The index indicates the carrier specified title string of Enahnce 4G LTE Mode settings.
+ * Default value is 0, which indicates the default title string.
+ * @hide
+ */
+ public static final String KEY_ENHANCED_4G_LTE_TITLE_VARIANT_INT =
+ "enhanced_4g_lte_title_variant_int";
+
+ /**
* Indicates whether the carrier wants to notify the user when handover of an LTE video call to
* WIFI fails.
* <p>
@@ -1947,6 +1984,17 @@
"skip_cf_fail_to_disable_dialog_bool";
/**
+ * Flag specifying whether operator supports including no reply condition timer option on
+ * CFNRy (3GPP TS 24.082 3: Call Forwarding on No Reply) in the call forwarding settings UI.
+ * {@code true} - include no reply condition timer option on CFNRy
+ * {@code false} - don't include no reply condition timer option on CFNRy
+ *
+ * @hide
+ */
+ public static final String KEY_SUPPORT_NO_REPLY_TIMER_FOR_CFNRY_BOOL =
+ "support_no_reply_timer_for_cfnry_bool";
+
+ /**
* List of the FAC (feature access codes) to dial as a normal call.
* @hide
*/
@@ -2086,6 +2134,16 @@
public static final String KEY_CALL_REDIRECTION_SERVICE_COMPONENT_NAME_STRING =
"call_redirection_service_component_name_string";
+ /**
+ * Flag specifying whether to show notification(call blocking disabled) when Enhanced Call
+ * Blocking(KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL) is enabled and making emergency call.
+ * When true, notification is shown always.
+ * When false, notification is shown only when any setting of "Enhanced Blocked number" is
+ * enabled.
+ */
+ public static final String KEY_SHOW_CALL_BLOCKING_DISABLED_NOTIFICATION_ALWAYS_BOOL =
+ "show_call_blocking_disabled_notification_always_bool";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -2142,6 +2200,7 @@
sDefaults.putBoolean(KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL, true);
sDefaults.putBoolean(KEY_HAS_IN_CALL_NOISE_SUPPRESSION_BOOL, false);
sDefaults.putBoolean(KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+ sDefaults.putBoolean(KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL, false);
sDefaults.putBoolean(KEY_SIMPLIFIED_NETWORK_SETTINGS_BOOL, false);
sDefaults.putBoolean(KEY_HIDE_SIM_LOCK_SETTINGS_BOOL, false);
@@ -2264,6 +2323,7 @@
sDefaults.putStringArray(KEY_WFC_OPERATOR_ERROR_CODES_STRING_ARRAY, null);
sDefaults.putInt(KEY_WFC_SPN_FORMAT_IDX_INT, 0);
sDefaults.putInt(KEY_WFC_DATA_SPN_FORMAT_IDX_INT, 0);
+ sDefaults.putBoolean(KEY_WFC_SPN_USE_ROOT_LOCALE, false);
sDefaults.putString(KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING, "");
sDefaults.putBoolean(KEY_CONFIG_WIFI_DISABLE_IN_ECBM, false);
sDefaults.putBoolean(KEY_CARRIER_NAME_OVERRIDE_BOOL, false);
@@ -2273,7 +2333,7 @@
sDefaults.putBoolean(KEY_SUPPORT_DIRECT_FDN_DIALING_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL, false);
sDefaults.putBoolean(KEY_SKIP_CF_FAIL_TO_DISABLE_DIALOG_BOOL, false);
- sDefaults.putBoolean(KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL, false);
+ sDefaults.putBoolean(KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL, true);
// MMS defaults
sDefaults.putBoolean(KEY_MMS_ALIAS_ENABLED_BOOL, false);
@@ -2370,6 +2430,7 @@
sDefaults.putStringArray(KEY_IMS_REASONINFO_MAPPING_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_ENHANCED_4G_LTE_TITLE_VARIANT_BOOL, false);
+ sDefaults.putInt(KEY_ENHANCED_4G_LTE_TITLE_VARIANT_INT, 0);
sDefaults.putBoolean(KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL, false);
sDefaults.putStringArray(KEY_FILTERED_CNAP_NAMES_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false);
@@ -2399,6 +2460,7 @@
sDefaults.putBoolean(KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, false);
sDefaults.putBoolean(KEY_RTT_SUPPORTED_BOOL, false);
sDefaults.putBoolean(KEY_DISABLE_CHARGE_INDICATION_BOOL, false);
+ sDefaults.putBoolean(KEY_SUPPORT_NO_REPLY_TIMER_FOR_CFNRY_BOOL, true);
sDefaults.putStringArray(KEY_FEATURE_ACCESS_CODES_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_IDENTIFY_HIGH_DEFINITION_CALLS_IN_CALL_LOG_BOOL, false);
sDefaults.putBoolean(KEY_SHOW_PRECISE_FAILED_CAUSE_BOOL, false);
@@ -2422,6 +2484,7 @@
});
sDefaults.putString(KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING, "");
sDefaults.putBoolean(KEY_CONFIG_SHOW_ORIG_DIAL_STRING_FOR_CDMA_BOOL, false);
+ sDefaults.putBoolean(KEY_SHOW_CALL_BLOCKING_DISABLED_NOTIFICATION_ALWAYS_BOOL, false);
}
/**
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index ee5cdc2..d7169b2 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -319,6 +319,29 @@
*/
public static final int IMS_SIP_ALTERNATE_EMERGENCY_CALL = 71;
+ /**
+ * Indicates that a new outgoing call cannot be placed because there is already an outgoing
+ * call dialing out.
+ */
+ public static final int ALREADY_DIALING = 72;
+
+ /**
+ * Indicates that a new outgoing call cannot be placed while there is a ringing call.
+ */
+ public static final int CANT_CALL_WHILE_RINGING = 73;
+
+ /**
+ * Indicates that a new outgoing call cannot be placed because calling has been disabled using
+ * the ro.telephony.disable-call system property.
+ */
+ public static final int CALLING_DISABLED = 74;
+
+ /**
+ * Indicates that a new outgoing call cannot be placed because there is currently an ongoing
+ * foreground and background call.
+ */
+ public static final int TOO_MANY_ONGOING_CALLS = 75;
+
//*********************************************************************************************
// When adding a disconnect type:
// 1) Update toString() with the newly added disconnect type.
@@ -474,6 +497,14 @@
return "NORMAL_UNSPECIFIED";
case IMS_SIP_ALTERNATE_EMERGENCY_CALL:
return "IMS_SIP_ALTERNATE_EMERGENCY_CALL";
+ case ALREADY_DIALING:
+ return "ALREADY_DIALING";
+ case CANT_CALL_WHILE_RINGING:
+ return "CANT_CALL_WHILE_RINGING";
+ case CALLING_DISABLED:
+ return "CALLING_DISABLED";
+ case TOO_MANY_ONGOING_CALLS:
+ return "TOO_MANY_ONGOING_CALLS";
default:
return "INVALID: " + cause;
}
diff --git a/telephony/java/android/telephony/MbmsGroupCallSession.java b/telephony/java/android/telephony/MbmsGroupCallSession.java
new file mode 100644
index 0000000..e373797
--- /dev/null
+++ b/telephony/java/android/telephony/MbmsGroupCallSession.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 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 android.telephony;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.telephony.mbms.GroupCall;
+import android.telephony.mbms.GroupCallCallback;
+import android.telephony.mbms.InternalGroupCallCallback;
+import android.telephony.mbms.InternalGroupCallSessionCallback;
+import android.telephony.mbms.MbmsErrors;
+import android.telephony.mbms.MbmsGroupCallSessionCallback;
+import android.telephony.mbms.MbmsUtils;
+import android.telephony.mbms.vendor.IMbmsGroupCallService;
+import android.util.ArraySet;
+import android.util.Log;
+
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * This class provides functionality for accessing group call functionality over MBMS.
+ */
+public class MbmsGroupCallSession implements AutoCloseable {
+ private static final String LOG_TAG = "MbmsGroupCallSession";
+
+ /**
+ * Service action which must be handled by the middleware implementing the MBMS group call
+ * interface.
+ * @hide
+ */
+ @SystemApi
+ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+ public static final String MBMS_GROUP_CALL_SERVICE_ACTION =
+ "android.telephony.action.EmbmsGroupCall";
+
+ /**
+ * Metadata key that specifies the component name of the service to bind to for group calls.
+ * @hide
+ */
+ @TestApi
+ public static final String MBMS_GROUP_CALL_SERVICE_OVERRIDE_METADATA =
+ "mbms-group-call-service-override";
+
+ private static AtomicBoolean sIsInitialized = new AtomicBoolean(false);
+
+ private AtomicReference<IMbmsGroupCallService> mService = new AtomicReference<>(null);
+ private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
+ @Override
+ public void binderDied() {
+ sIsInitialized.set(false);
+ mInternalCallback.onError(MbmsErrors.ERROR_MIDDLEWARE_LOST,
+ "Received death notification");
+ }
+ };
+
+ private InternalGroupCallSessionCallback mInternalCallback;
+ private Set<GroupCall> mKnownActiveGroupCalls = new ArraySet<>();
+
+ private final Context mContext;
+ private int mSubscriptionId;
+
+ /** @hide */
+ private MbmsGroupCallSession(Context context, Executor executor, int subscriptionId,
+ MbmsGroupCallSessionCallback callback) {
+ mContext = context;
+ mSubscriptionId = subscriptionId;
+ mInternalCallback = new InternalGroupCallSessionCallback(callback, executor);
+ }
+
+ /**
+ * Create a new {@link MbmsGroupCallSession} using the given subscription ID.
+ *
+ * You may only have one instance of {@link MbmsGroupCallSession} per UID. If you call this
+ * method while there is an active instance of {@link MbmsGroupCallSession} in your process
+ * (in other words, one that has not had {@link #close()} called on it), this method will
+ * throw an {@link IllegalStateException}. If you call this method in a different process
+ * running under the same UID, an error will be indicated via
+ * {@link MbmsGroupCallSessionCallback#onError(int, String)}.
+ *
+ * Note that initialization may fail asynchronously. If you wish to try again after you
+ * receive such an asynchronous error, you must call {@link #close()} on the instance of
+ * {@link MbmsGroupCallSession} that you received before calling this method again.
+ *
+ * @param context The {@link Context} to use.
+ * @param executor The executor on which you wish to execute callbacks.
+ * @param subscriptionId The subscription ID to use.
+ * @param callback A callback object on which you wish to receive results of asynchronous
+ * operations.
+ * @return An instance of {@link MbmsGroupCallSession}, or null if an error occurred.
+ */
+ public static @Nullable MbmsGroupCallSession create(@NonNull Context context,
+ @NonNull Executor executor, int subscriptionId,
+ final @NonNull MbmsGroupCallSessionCallback callback) {
+ if (!sIsInitialized.compareAndSet(false, true)) {
+ throw new IllegalStateException("Cannot create two instances of MbmsGroupCallSession");
+ }
+ MbmsGroupCallSession session = new MbmsGroupCallSession(context, executor,
+ subscriptionId, callback);
+
+ final int result = session.bindAndInitialize();
+ if (result != MbmsErrors.SUCCESS) {
+ sIsInitialized.set(false);
+ executor.execute(new Runnable() {
+ @Override
+ public void run() {
+ callback.onError(result, null);
+ }
+ });
+ return null;
+ }
+ return session;
+ }
+
+ /**
+ * Create a new {@link MbmsGroupCallSession} using the system default data subscription ID.
+ * See {@link #create(Context, Executor, int, MbmsGroupCallSessionCallback)}.
+ */
+ public static MbmsGroupCallSession create(@NonNull Context context,
+ @NonNull Executor executor, @NonNull MbmsGroupCallSessionCallback callback) {
+ return create(context, executor, SubscriptionManager.getDefaultSubscriptionId(), callback);
+ }
+
+ /**
+ * Terminates this instance. Also terminates
+ * any group calls spawned from this instance as if
+ * {@link GroupCall#close()} had been called on them. After this method returns,
+ * no further callbacks originating from the middleware will be enqueued on the provided
+ * instance of {@link MbmsGroupCallSessionCallback}, but callbacks that have already been
+ * enqueued will still be delivered.
+ *
+ * It is safe to call {@link #create(Context, Executor, int, MbmsGroupCallSessionCallback)} to
+ * obtain another instance of {@link MbmsGroupCallSession} immediately after this method
+ * returns.
+ *
+ * May throw an {@link IllegalStateException}
+ */
+ public void close() {
+ try {
+ IMbmsGroupCallService groupCallService = mService.get();
+ if (groupCallService == null) {
+ // Ignore and return, assume already disposed.
+ return;
+ }
+ groupCallService.dispose(mSubscriptionId);
+ for (GroupCall s : mKnownActiveGroupCalls) {
+ s.getCallback().stop();
+ }
+ mKnownActiveGroupCalls.clear();
+ } catch (RemoteException e) {
+ // Ignore for now
+ } finally {
+ mService.set(null);
+ sIsInitialized.set(false);
+ mInternalCallback.stop();
+ }
+ }
+
+ /**
+ * Starts the requested group call, reporting status to the indicated callback.
+ * Returns an object used to control that call.
+ *
+ * May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
+ *
+ * Asynchronous errors through the callback include any of the errors in
+ * {@link MbmsErrors.GeneralErrors}.
+ *
+ * @param executor The executor on which you wish to execute callbacks for this stream.
+ * @param tmgi The TMGI, an identifier for the group call you want to join.
+ * @param saiArray An array of SAIs for the group call that should be negotiated separately with
+ * the carrier.
+ * @param frequencyArray An array of frequencies for the group call that should be negotiated
+ * separately with the carrier.
+ * @param callback The callback that you want to receive information about the call on.
+ * @return An instance of {@link GroupCall} through which the call can be controlled.
+ * May be {@code null} if an error occurred.
+ */
+ public @Nullable GroupCall startGroupCall(@NonNull Executor executor, long tmgi, int[] saiArray,
+ int[] frequencyArray, @NonNull GroupCallCallback callback) {
+ IMbmsGroupCallService groupCallService = mService.get();
+ if (groupCallService == null) {
+ throw new IllegalStateException("Middleware not yet bound");
+ }
+
+ InternalGroupCallCallback serviceCallback = new InternalGroupCallCallback(
+ callback, executor);
+
+ GroupCall serviceForApp = new GroupCall(mSubscriptionId,
+ groupCallService, this, tmgi, serviceCallback);
+ mKnownActiveGroupCalls.add(serviceForApp);
+
+ try {
+ int returnCode = groupCallService.startGroupCall(
+ mSubscriptionId, tmgi, saiArray, frequencyArray, serviceCallback);
+ if (returnCode == MbmsErrors.UNKNOWN) {
+ // Unbind and throw an obvious error
+ close();
+ throw new IllegalStateException("Middleware must not return an unknown error code");
+ }
+ if (returnCode != MbmsErrors.SUCCESS) {
+ mInternalCallback.onError(returnCode, null);
+ return null;
+ }
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Remote process died");
+ mService.set(null);
+ sIsInitialized.set(false);
+ mInternalCallback.onError(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+ return null;
+ }
+
+ return serviceForApp;
+ }
+
+ /** @hide */
+ public void onGroupCallStopped(GroupCall service) {
+ mKnownActiveGroupCalls.remove(service);
+ }
+
+ private int bindAndInitialize() {
+ return MbmsUtils.startBinding(mContext, MBMS_GROUP_CALL_SERVICE_ACTION,
+ new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ IMbmsGroupCallService groupCallService =
+ IMbmsGroupCallService.Stub.asInterface(service);
+ int result;
+ try {
+ result = groupCallService.initialize(mInternalCallback,
+ mSubscriptionId);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Service died before initialization");
+ mInternalCallback.onError(
+ MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
+ e.toString());
+ sIsInitialized.set(false);
+ return;
+ } catch (RuntimeException e) {
+ Log.e(LOG_TAG, "Runtime exception during initialization");
+ mInternalCallback.onError(
+ MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
+ e.toString());
+ sIsInitialized.set(false);
+ return;
+ }
+ if (result == MbmsErrors.UNKNOWN) {
+ // Unbind and throw an obvious error
+ close();
+ throw new IllegalStateException("Middleware must not return"
+ + " an unknown error code");
+ }
+ if (result != MbmsErrors.SUCCESS) {
+ mInternalCallback.onError(result,
+ "Error returned during initialization");
+ sIsInitialized.set(false);
+ return;
+ }
+ try {
+ groupCallService.asBinder().linkToDeath(mDeathRecipient, 0);
+ } catch (RemoteException e) {
+ mInternalCallback.onError(MbmsErrors.ERROR_MIDDLEWARE_LOST,
+ "Middleware lost during initialization");
+ sIsInitialized.set(false);
+ return;
+ }
+ mService.set(groupCallService);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ sIsInitialized.set(false);
+ mService.set(null);
+ }
+ });
+ }
+}
diff --git a/telephony/java/android/telephony/NeighboringCellInfo.java b/telephony/java/android/telephony/NeighboringCellInfo.java
index 8e99518..79298fd 100644
--- a/telephony/java/android/telephony/NeighboringCellInfo.java
+++ b/telephony/java/android/telephony/NeighboringCellInfo.java
@@ -32,7 +32,12 @@
/**
* Represents the neighboring cell information, including
* Received Signal Strength and Cell ID location.
+ *
+ * @deprecated This class should not be used by any app targeting
+ * {@link Build.VERSION_CODES.Q Android Q} or higher. Instead callers should use
+ * {@Link android.telephony.CellInfo CellInfo}.
*/
+@Deprecated
public class NeighboringCellInfo implements Parcelable
{
/**
diff --git a/telephony/java/android/telephony/NetworkScan.java b/telephony/java/android/telephony/NetworkScan.java
index 7c7d7a0..202da68 100644
--- a/telephony/java/android/telephony/NetworkScan.java
+++ b/telephony/java/android/telephony/NetworkScan.java
@@ -16,11 +16,10 @@
package android.telephony;
+import android.annotation.IntDef;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.annotation.IntDef;
-import android.util.Log;
import com.android.internal.telephony.ITelephony;
@@ -113,6 +112,8 @@
}
try {
telephony.stopNetworkScan(mSubId, mScanId);
+ } catch (IllegalArgumentException ex) {
+ Rlog.d(TAG, "stopNetworkScan - no active scan for ScanID=" + mScanId);
} catch (RemoteException ex) {
Rlog.e(TAG, "stopNetworkScan RemoteException", ex);
} catch (RuntimeException ex) {
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index bd6a59d..498be96 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -23,6 +23,7 @@
import android.os.Looper;
import android.os.Message;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.IPhoneStateListener;
import java.lang.ref.WeakReference;
@@ -778,8 +779,12 @@
}
}
+ /**
+ * @hide
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@UnsupportedAppUsage
- IPhoneStateListener callback = new IPhoneStateListenerStub(this);
+ public final IPhoneStateListener callback = new IPhoneStateListenerStub(this);
private void log(String s) {
Rlog.d(LOG_TAG, s);
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index f2b73dc..7469186 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -24,6 +24,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
+import android.telephony.NetworkRegistrationState.Domain;
import android.text.TextUtils;
import java.lang.annotation.Retention;
@@ -1595,7 +1596,7 @@
/**
* Get all of the available network registration states.
*
- * @return List of registration states
+ * @return List of {@link NetworkRegistrationState}
* @hide
*/
@SystemApi
@@ -1606,14 +1607,30 @@
}
/**
- * Get the network registration states with given transport type.
+ * Get the network registration states for the transport type.
*
- * @param transportType The transport type. See {@link AccessNetworkConstants.TransportType}
- * @return List of registration states.
+ * @param transportType The {@link AccessNetworkConstants.TransportType transport type}
+ * @return List of {@link NetworkRegistrationState}
+ * @hide
+ *
+ * @deprecated Use {@link #getNetworkRegistrationStatesFromTransportType(int)}
+ */
+ @Deprecated
+ @SystemApi
+ public List<NetworkRegistrationState> getNetworkRegistrationStates(int transportType) {
+ return getNetworkRegistrationStatesForTransportType(transportType);
+ }
+
+ /**
+ * Get the network registration states for the transport type.
+ *
+ * @param transportType The {@link AccessNetworkConstants.TransportType transport type}
+ * @return List of {@link NetworkRegistrationState}
* @hide
*/
@SystemApi
- public List<NetworkRegistrationState> getNetworkRegistrationStates(int transportType) {
+ public List<NetworkRegistrationState> getNetworkRegistrationStatesForTransportType(
+ int transportType) {
List<NetworkRegistrationState> list = new ArrayList<>();
synchronized (mNetworkRegistrationStates) {
@@ -1628,16 +1645,57 @@
}
/**
- * Get the network registration states with given transport type and domain.
+ * Get the network registration states for the network domain.
*
- * @param domain The network domain. Must be {@link NetworkRegistrationState#DOMAIN_CS} or
- * {@link NetworkRegistrationState#DOMAIN_PS}.
- * @param transportType The transport type. See {@link AccessNetworkConstants.TransportType}
- * @return The matching NetworkRegistrationState.
+ * @param domain The network {@link NetworkRegistrationState.Domain domain}
+ * @return List of {@link NetworkRegistrationState}
* @hide
*/
@SystemApi
- public NetworkRegistrationState getNetworkRegistrationStates(int domain, int transportType) {
+ public List<NetworkRegistrationState> getNetworkRegistrationStatesForDomain(
+ @Domain int domain) {
+ List<NetworkRegistrationState> list = new ArrayList<>();
+
+ synchronized (mNetworkRegistrationStates) {
+ for (NetworkRegistrationState networkRegistrationState : mNetworkRegistrationStates) {
+ if (networkRegistrationState.getDomain() == domain) {
+ list.add(networkRegistrationState);
+ }
+ }
+ }
+
+ return list;
+ }
+
+ /**
+ * Get the network registration state for the transport type and network domain.
+ *
+ * @param domain The network {@link NetworkRegistrationState.Domain domain}
+ * @param transportType The {@link AccessNetworkConstants.TransportType transport type}
+ * @return The matching {@link NetworkRegistrationState}
+ * @hide
+ *
+ * @deprecated Use {@link #getNetworkRegistrationState(int, int)}
+ */
+ @Deprecated
+ @SystemApi
+ public NetworkRegistrationState getNetworkRegistrationStates(@Domain int domain,
+ int transportType) {
+ return getNetworkRegistrationState(domain, transportType);
+ }
+
+ /**
+ * Get the network registration state for the transport type and network domain.
+ *
+ * @param domain The network {@link NetworkRegistrationState.Domain domain}
+ * @param transportType The {@link AccessNetworkConstants.TransportType transport type}
+ * @return The matching {@link NetworkRegistrationState}
+ * @hide
+ *
+ */
+ @SystemApi
+ public NetworkRegistrationState getNetworkRegistrationState(@Domain int domain,
+ int transportType) {
synchronized (mNetworkRegistrationStates) {
for (NetworkRegistrationState networkRegistrationState : mNetworkRegistrationStates) {
if (networkRegistrationState.getTransportType() == transportType
@@ -1669,5 +1727,4 @@
mNetworkRegistrationStates.add(regState);
}
}
-
}
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index ec26622..22c1e58 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -33,11 +33,13 @@
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
/**
* A Parcelable class for Subscription Information.
@@ -552,11 +554,49 @@
String cardIdToPrint = givePrintableIccid(mCardId);
return "{id=" + mId + ", iccId=" + iccIdToPrint + " simSlotIndex=" + mSimSlotIndex
+ " displayName=" + mDisplayName + " carrierName=" + mCarrierName
- + " nameSource=" + mNameSource + " iconTint=" + mIconTint
+ + " nameSource=" + mNameSource + " iconTint=" + mIconTint + " mNumber=" + mNumber
+ " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc " + mMcc
- + " mnc " + mMnc + " isEmbedded " + mIsEmbedded
+ + " mnc " + mMnc + "mCountryIso=" + mCountryIso + " isEmbedded " + mIsEmbedded
+ " accessRules " + Arrays.toString(mAccessRules)
+ " cardId=" + cardIdToPrint + " isOpportunistic " + mIsOpportunistic
+ " parentSubId=" + mParentSubId + "}";
}
-}
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mId, mSimSlotIndex, mNameSource, mIconTint, mDataRoaming, mIsEmbedded,
+ mIsOpportunistic, mParentSubId, mIccId, mNumber, mMcc, mMnc, mCountryIso,
+ mCardId, mDisplayName, mCarrierName, mAccessRules);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) return false;
+ if (obj == this) return true;
+
+ SubscriptionInfo toCompare;
+ try {
+ toCompare = (SubscriptionInfo) obj;
+ } catch (ClassCastException ex) {
+ return false;
+ }
+
+ return mId == toCompare.mId
+ && mSimSlotIndex == toCompare.mSimSlotIndex
+ && mNameSource == toCompare.mNameSource
+ && mIconTint == toCompare.mIconTint
+ && mDataRoaming == toCompare.mDataRoaming
+ && mIsEmbedded == toCompare.mIsEmbedded
+ && mIsOpportunistic == toCompare.mIsOpportunistic
+ && mParentSubId == toCompare.mParentSubId
+ && Objects.equals(mIccId, toCompare.mIccId)
+ && Objects.equals(mNumber, toCompare.mNumber)
+ && Objects.equals(mMcc, toCompare.mMcc)
+ && Objects.equals(mMnc, toCompare.mMnc)
+ && Objects.equals(mCountryIso, toCompare.mCountryIso)
+ && Objects.equals(mCardId, toCompare.mCardId)
+ && TextUtils.equals(mDisplayName, toCompare.mDisplayName)
+ && TextUtils.equals(mCarrierName, toCompare.mCarrierName)
+ && Arrays.equals(mAccessRules, toCompare.mAccessRules);
+ }
+}
\ No newline at end of file
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 0c8280b..7a99c71 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -59,6 +59,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Locale;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -88,9 +89,7 @@
/** @hide */
public static final int INVALID_SIM_SLOT_INDEX = -1;
- /** Indicates the caller wants the default sub id. */
- /** @hide */
- @UnsupportedAppUsage
+ /** Indicates the default subscription ID in Telephony. */
public static final int DEFAULT_SUBSCRIPTION_ID = Integer.MAX_VALUE;
/**
@@ -1600,6 +1599,19 @@
}
/**
+ * Check if the subscription ID is usable.
+ *
+ * A usable subscription ID has a valid value except some special values such as
+ * {@link DEFAULT_SUBSCRIPTION_ID}. It can be used for subscription functions.
+ *
+ * @param subscriptionId the subscription ID
+ * @return {@code true} if the subscription ID is usable; {@code false} otherwise.
+ */
+ public static boolean isUsableSubscriptionId(int subscriptionId) {
+ return isUsableSubIdValue(subscriptionId);
+ }
+
+ /**
* @return true if subId is an usable subId value else false. A
* usable subId means its neither a INVALID_SUBSCRIPTION_ID nor a DEFAULT_SUB_ID.
* @hide
@@ -1810,6 +1822,19 @@
*/
@UnsupportedAppUsage
public static Resources getResourcesForSubId(Context context, int subId) {
+ return getResourcesForSubId(context, subId, false);
+ }
+
+ /**
+ * Returns the resources associated with Subscription.
+ * @param context Context object
+ * @param subId Subscription Id of Subscription who's resources are required
+ * @param useRootLocale if root locale should be used. Localized locale is used if false.
+ * @return Resources associated with Subscription.
+ * @hide
+ */
+ public static Resources getResourcesForSubId(Context context, int subId,
+ boolean useRootLocale) {
final SubscriptionInfo subInfo =
SubscriptionManager.from(context).getActiveSubscriptionInfo(subId);
@@ -1821,6 +1846,11 @@
newConfig.mnc = subInfo.getMnc();
if (newConfig.mnc == 0) newConfig.mnc = Configuration.MNC_ZERO;
}
+
+ if (useRootLocale) {
+ newConfig.setLocale(Locale.ROOT);
+ }
+
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
DisplayMetrics newMetrics = new DisplayMetrics();
newMetrics.setTo(metrics);
@@ -1828,6 +1858,19 @@
}
/**
+ * Checks if the supplied subscription ID corresponds to an active subscription.
+ *
+ * @param subscriptionId the subscription ID.
+ * @return {@code true} if the supplied subscription ID corresponds to an active subscription;
+ * {@code false} if it does not correspond to an active subscription; or throw a
+ * SecurityException if the caller hasn't got the right permission.
+ */
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ public boolean isActiveSubscriptionId(int subscriptionId) {
+ return isActiveSubId(subscriptionId);
+ }
+
+ /**
* @return true if the sub ID is active. i.e. The sub ID corresponds to a known subscription
* and the SIM providing the subscription is present in a slot and in "LOADED" state.
* @hide
@@ -1837,7 +1880,7 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- return iSub.isActiveSubId(subId);
+ return iSub.isActiveSubId(subId, mContext.getOpPackageName());
}
} catch (RemoteException ex) {
}
@@ -2116,7 +2159,12 @@
/**
* Set preferred default data.
- * Set on which slot default data will be on.
+ * Set on which slot most cellular data will be on.
+ * It's also usually what we set up internet connection on.
+ *
+ * PreferredData overwrites user setting of default data subscription. And it's used
+ * by ANAS or carrier apps to switch primary and CBRS subscription dynamically in multi-SIM
+ * devices.
*
* @param slotId which slot is preferred to for cellular data.
* @hide
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index ebe05e8..48f38fc 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -16,6 +16,8 @@
package android.telephony;
+import static android.content.Context.TELECOM_SERVICE;
+
import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.IntDef;
@@ -67,6 +69,7 @@
import com.android.internal.telephony.IPhoneSubInfo;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.ITelephonyRegistry;
+import com.android.internal.telephony.OperatorInfo;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.TelephonyProperties;
@@ -163,7 +166,6 @@
/** @hide */
static public final int OTASP_SIM_UNPROVISIONED = 5;
-
/** @hide */
static public final int KEY_TYPE_EPDG = 1;
@@ -1576,6 +1578,7 @@
*
* @return List of NeighboringCellInfo or null if info unavailable.
*
+ * @removed
* @deprecated Use {@link #getAllCellInfo} which returns a superset of the information
* from NeighboringCellInfo, including LTE cell information.
*/
@@ -2088,10 +2091,37 @@
/** Max network type number. Update as new types are added. Don't add negative types. {@hide} */
public static final int MAX_NETWORK_TYPE = NETWORK_TYPE_LTE_CA;
+
+ /** @hide */
+ @IntDef({
+ NETWORK_TYPE_UNKNOWN,
+ NETWORK_TYPE_GPRS,
+ NETWORK_TYPE_EDGE,
+ NETWORK_TYPE_UMTS,
+ NETWORK_TYPE_CDMA,
+ NETWORK_TYPE_EVDO_0,
+ NETWORK_TYPE_EVDO_A,
+ NETWORK_TYPE_1xRTT,
+ NETWORK_TYPE_HSDPA,
+ NETWORK_TYPE_HSUPA,
+ NETWORK_TYPE_HSPA,
+ NETWORK_TYPE_IDEN,
+ NETWORK_TYPE_EVDO_B,
+ NETWORK_TYPE_LTE,
+ NETWORK_TYPE_EHRPD,
+ NETWORK_TYPE_HSPAP,
+ NETWORK_TYPE_GSM,
+ NETWORK_TYPE_TD_SCDMA,
+ NETWORK_TYPE_IWLAN,
+ NETWORK_TYPE_LTE_CA,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface NetworkType{}
+
/**
* @return the NETWORK_TYPE_xxxx for current data connection.
*/
- public int getNetworkType() {
+ public @NetworkType int getNetworkType() {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
@@ -2136,24 +2166,24 @@
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- @UnsupportedAppUsage
- public int getNetworkType(int subId) {
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- return telephony.getNetworkTypeForSubscriber(subId, getOpPackageName());
- } else {
- // This can happen when the ITelephony interface is not up yet.
- return NETWORK_TYPE_UNKNOWN;
- }
- } catch(RemoteException ex) {
- // This shouldn't happen in the normal case
- return NETWORK_TYPE_UNKNOWN;
- } catch (NullPointerException ex) {
- // This could happen before phone restarts due to crashing
- return NETWORK_TYPE_UNKNOWN;
- }
- }
+ @UnsupportedAppUsage
+ public int getNetworkType(int subId) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.getNetworkTypeForSubscriber(subId, getOpPackageName());
+ } else {
+ // This can happen when the ITelephony interface is not up yet.
+ return NETWORK_TYPE_UNKNOWN;
+ }
+ } catch (RemoteException ex) {
+ // This shouldn't happen in the normal case
+ return NETWORK_TYPE_UNKNOWN;
+ } catch (NullPointerException ex) {
+ // This could happen before phone restarts due to crashing
+ return NETWORK_TYPE_UNKNOWN;
+ }
+ }
/**
* Returns a constant indicating the radio technology (network type)
@@ -2186,7 +2216,7 @@
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- public int getDataNetworkType() {
+ public @NetworkType int getDataNetworkType() {
return getDataNetworkType(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
}
@@ -2226,7 +2256,7 @@
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- public int getVoiceNetworkType() {
+ public @NetworkType int getVoiceNetworkType() {
return getVoiceNetworkType(getSubId());
}
@@ -2883,7 +2913,7 @@
* of time the mode may be unknown.
*
* <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
- * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+ * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
*
* @return {@link PhoneConstants#LTE_ON_CDMA_UNKNOWN}, {@link PhoneConstants#LTE_ON_CDMA_FALSE}
* or {@link PhoneConstants#LTE_ON_CDMA_TRUE}
@@ -4138,11 +4168,16 @@
}
/**
- * Returns the IMS home network domain name that was loaded from the ISIM.
- * @return the IMS domain name, or null if not present or not loaded
+ * Returns the IMS home network domain name that was loaded from the ISIM {@see #APPTYPE_ISIM}.
+ * @return the IMS domain name. Returns {@code null} if ISIM hasn't been loaded or IMS domain
+ * hasn't been loaded or isn't present on the ISIM.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String getIsimDomain() {
try {
IPhoneSubInfo info = getSubscriberInfo();
@@ -4370,7 +4405,7 @@
* @hide
*/
private ITelecomService getTelecomService() {
- return ITelecomService.Stub.asInterface(ServiceManager.getService(Context.TELECOM_SERVICE));
+ return ITelecomService.Stub.asInterface(ServiceManager.getService(TELECOM_SERVICE));
}
private ITelephonyRegistry getTelephonyRegistry() {
@@ -5396,7 +5431,19 @@
}
}
- // ICC SIM Application Types
+ /**
+ * UICC SIM Application Types
+ * @hide
+ */
+ @IntDef(prefix = { "APPTYPE_" }, value = {
+ APPTYPE_SIM,
+ APPTYPE_USIM,
+ APPTYPE_RUIM,
+ APPTYPE_CSIM,
+ APPTYPE_ISIM
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface UiccAppType{}
/** UICC application type is SIM */
public static final int APPTYPE_SIM = PhoneConstants.APPTYPE_SIM;
/** UICC application type is USIM */
@@ -5407,6 +5454,7 @@
public static final int APPTYPE_CSIM = PhoneConstants.APPTYPE_CSIM;
/** UICC application type is ISIM */
public static final int APPTYPE_ISIM = PhoneConstants.APPTYPE_ISIM;
+
// authContext (parameter P2) when doing UICC challenge,
// per 3GPP TS 31.102 (Section 7.1.2)
/** Authentication type for UICC challenge is EAP SIM. See RFC 4186 for details. */
@@ -5658,23 +5706,6 @@
}
/**
- * @return true if the IMS resolver is busy resolving a binding and should not be considered
- * available, false if the IMS resolver is idle.
- * @hide
- */
- public boolean isResolvingImsBinding() {
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- return telephony.isResolvingImsBinding();
- }
- } catch (RemoteException e) {
- Rlog.e(TAG, "isResolvingImsBinding, RemoteException: " + e.getMessage());
- }
- return false;
- }
-
- /**
* Set IMS registration state
*
* @param Registration state
@@ -5690,6 +5721,203 @@
}
}
+ /** @hide */
+ @IntDef(prefix = { "NETWORK_MODE_" }, value = {
+ NETWORK_MODE_WCDMA_PREF,
+ NETWORK_MODE_GSM_ONLY,
+ NETWORK_MODE_WCDMA_ONLY,
+ NETWORK_MODE_GSM_UMTS,
+ NETWORK_MODE_CDMA_EVDO,
+ NETWORK_MODE_CDMA_NO_EVDO,
+ NETWORK_MODE_EVDO_NO_CDMA,
+ NETWORK_MODE_GLOBAL,
+ NETWORK_MODE_LTE_CDMA_EVDO,
+ NETWORK_MODE_LTE_GSM_WCDMA,
+ NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA,
+ NETWORK_MODE_LTE_ONLY,
+ NETWORK_MODE_LTE_WCDMA,
+ NETWORK_MODE_TDSCDMA_ONLY,
+ NETWORK_MODE_TDSCDMA_WCDMA,
+ NETWORK_MODE_LTE_TDSCDMA,
+ NETWORK_MODE_TDSCDMA_GSM,
+ NETWORK_MODE_LTE_TDSCDMA_GSM,
+ NETWORK_MODE_TDSCDMA_GSM_WCDMA,
+ NETWORK_MODE_LTE_TDSCDMA_WCDMA,
+ NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA,
+ NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA,
+ NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PrefNetworkMode{}
+
+ /**
+ * network mode is GSM/WCDMA (WCDMA preferred).
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_WCDMA_PREF = RILConstants.NETWORK_MODE_WCDMA_PREF;
+
+ /**
+ * network mode is GSM only.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_GSM_ONLY = RILConstants.NETWORK_MODE_GSM_ONLY;
+
+ /**
+ * network mode is WCDMA only.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_WCDMA_ONLY = RILConstants.NETWORK_MODE_WCDMA_ONLY;
+
+ /**
+ * network mode is GSM/WCDMA (auto mode, according to PRL).
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_GSM_UMTS = RILConstants.NETWORK_MODE_GSM_UMTS;
+
+ /**
+ * network mode is CDMA and EvDo (auto mode, according to PRL).
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_CDMA_EVDO = RILConstants.NETWORK_MODE_CDMA;
+
+ /**
+ * network mode is CDMA only.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_CDMA_NO_EVDO = RILConstants.NETWORK_MODE_CDMA_NO_EVDO;
+
+ /**
+ * network mode is EvDo only.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_EVDO_NO_CDMA = RILConstants.NETWORK_MODE_EVDO_NO_CDMA;
+
+ /**
+ * network mode is GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL).
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_GLOBAL = RILConstants.NETWORK_MODE_GLOBAL;
+
+ /**
+ * network mode is LTE, CDMA and EvDo.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_LTE_CDMA_EVDO = RILConstants.NETWORK_MODE_LTE_CDMA_EVDO;
+
+ /**
+ * preferred network mode is LTE, GSM/WCDMA.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_LTE_GSM_WCDMA = RILConstants.NETWORK_MODE_LTE_GSM_WCDMA;
+
+ /**
+ * network mode is LTE, CDMA, EvDo, GSM/WCDMA.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA =
+ RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA;
+
+ /**
+ * network mode is LTE Only.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_LTE_ONLY = RILConstants.NETWORK_MODE_LTE_ONLY;
+
+ /**
+ * network mode is LTE/WCDMA.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_LTE_WCDMA = RILConstants.NETWORK_MODE_LTE_WCDMA;
+
+ /**
+ * network mode is TD-SCDMA only.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_TDSCDMA_ONLY = RILConstants.NETWORK_MODE_TDSCDMA_ONLY;
+
+ /**
+ * network mode is TD-SCDMA and WCDMA.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_TDSCDMA_WCDMA = RILConstants.NETWORK_MODE_TDSCDMA_WCDMA;
+
+ /**
+ * network mode is TD-SCDMA and LTE.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_LTE_TDSCDMA = RILConstants.NETWORK_MODE_LTE_TDSCDMA;
+
+ /**
+ * network mode is TD-SCDMA and GSM.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_TDSCDMA_GSM = RILConstants.NETWORK_MODE_TDSCDMA_GSM;
+
+ /**
+ * network mode is TD-SCDMA,GSM and LTE.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_LTE_TDSCDMA_GSM =
+ RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM;
+
+ /**
+ * network mode is TD-SCDMA, GSM/WCDMA.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_TDSCDMA_GSM_WCDMA =
+ RILConstants.NETWORK_MODE_TDSCDMA_GSM_WCDMA;
+
+ /**
+ * network mode is TD-SCDMA, WCDMA and LTE.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_LTE_TDSCDMA_WCDMA =
+ RILConstants.NETWORK_MODE_LTE_TDSCDMA_WCDMA;
+
+ /**
+ * network mode is TD-SCDMA, GSM/WCDMA and LTE.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA =
+ RILConstants.NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA;
+
+ /**
+ * network mode is TD-SCDMA,EvDo,CDMA,GSM/WCDMA.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA =
+ RILConstants.NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
+
+ /**
+ * network mode is TD-SCDMA/LTE/GSM/WCDMA, CDMA, and EvDo.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA =
+ RILConstants.NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA;
+
/**
* Get the preferred network type.
* Used for device configuration by some CDMA operators.
@@ -5698,11 +5926,12 @@
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
* app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
- * @return the preferred network type, defined in RILConstants.java.
+ * @return the preferred network type.
* @hide
*/
- @UnsupportedAppUsage
- public int getPreferredNetworkType(int subId) {
+ @RequiresPermission((android.Manifest.permission.MODIFY_PHONE_STATE))
+ @SystemApi
+ public @PrefNetworkMode int getPreferredNetworkType(int subId) {
try {
ITelephony telephony = getITelephony();
if (telephony != null)
@@ -5719,7 +5948,7 @@
* Sets the network selection mode to automatic.
*
* <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
- * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+ * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
*
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
@@ -5744,7 +5973,7 @@
* Perform a radio scan and return the list of available networks.
*
* <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
- * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+ * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
*
* <p> Note that this scan can take a long time (sometimes minutes) to happen.
*
@@ -5823,7 +6052,7 @@
* Ask the radio to connect to the input network and change selection mode to manual.
*
* <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
- * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+ * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
*
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
@@ -5833,21 +6062,46 @@
* @param persistSelection whether the selection will persist until reboot. If true, only allows
* attaching to the selected PLMN until reboot; otherwise, attach to the chosen PLMN and resume
* normal network selection next time.
- * @return true on success; false on any failure.
+ * @return {@code true} on success; {@code false} on any failure.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean setNetworkSelectionModeManual(String operatorNumeric, boolean persistSelection) {
+ return setNetworkSelectionModeManual(
+ new OperatorInfo(
+ "" /* operatorAlphaLong */, "" /* operatorAlphaShort */, operatorNumeric),
+ persistSelection);
+ }
+
+ /**
+ * Ask the radio to connect to the input network and change selection mode to manual.
+ *
+ * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+ * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+ * app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
+ * @param operatorInfo included the PLMN id, long name, short name of the operator to attach to.
+ * @param persistSelection whether the selection will persist until reboot. If true, only allows
+ * attaching to the selected PLMN until reboot; otherwise, attach to the chosen PLMN and resume
+ * normal network selection next time.
+ * @return {@code true} on success; {@code true} on any failure.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public boolean setNetworkSelectionModeManual(
+ OperatorInfo operatorInfo, boolean persistSelection) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
return telephony.setNetworkSelectionModeManual(
- getSubId(), operatorNumeric, persistSelection);
+ getSubId(), operatorInfo, persistSelection);
}
} catch (RemoteException ex) {
Rlog.e(TAG, "setNetworkSelectionModeManual RemoteException", ex);
- } catch (NullPointerException ex) {
- Rlog.e(TAG, "setNetworkSelectionModeManual NPE", ex);
}
return false;
}
@@ -5856,7 +6110,7 @@
* Get the network selection mode.
*
* <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
- * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+ * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
* @return the network selection mode.
*
@@ -6259,57 +6513,42 @@
}
/**
- * @deprecated Use {@link android.telecom.TelecomManager#endCall()} instead.
+ * @removed Use {@link android.telecom.TelecomManager#endCall()} instead.
* @hide
+ * @removed
*/
@Deprecated
@SystemApi
@RequiresPermission(android.Manifest.permission.CALL_PHONE)
public boolean endCall() {
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null)
- return telephony.endCall();
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#endCall", e);
- }
return false;
}
/**
- * @deprecated Use {@link android.telecom.TelecomManager#acceptRingingCall} instead
+ * @removed Use {@link android.telecom.TelecomManager#acceptRingingCall} instead
* @hide
+ * @removed
*/
@Deprecated
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void answerRingingCall() {
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null)
- telephony.answerRingingCall();
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#answerRingingCall", e);
- }
+ // No-op
}
/**
- * @deprecated Use {@link android.telecom.TelecomManager#silenceRinger} instead
+ * @removed Use {@link android.telecom.TelecomManager#silenceRinger} instead
* @hide
*/
@Deprecated
@SystemApi
@SuppressLint("Doclava125")
public void silenceRinger() {
- try {
- getTelecomService().silenceRinger(getOpPackageName());
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelecomService#silenceRinger", e);
- }
+ // No-op
}
/**
- * @deprecated Use {@link android.telecom.TelecomManager#isInCall} instead
+ * @removed Use {@link android.telecom.TelecomManager#isInCall} instead
* @hide
*/
@Deprecated
@@ -6319,18 +6558,11 @@
android.Manifest.permission.READ_PHONE_STATE
})
public boolean isOffhook() {
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null)
- return telephony.isOffhook(getOpPackageName());
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#isOffhook", e);
- }
return false;
}
/**
- * @deprecated Use {@link android.telecom.TelecomManager#isRinging} instead
+ * @removed Use {@link android.telecom.TelecomManager#isRinging} instead
* @hide
*/
@Deprecated
@@ -6340,18 +6572,11 @@
android.Manifest.permission.READ_PHONE_STATE
})
public boolean isRinging() {
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null)
- return telephony.isRinging(getOpPackageName());
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#isRinging", e);
- }
return false;
}
/**
- * @deprecated Use {@link android.telecom.TelecomManager#isInCall} instead
+ * @removed Use {@link android.telecom.TelecomManager#isInCall} instead
* @hide
*/
@Deprecated
@@ -6361,13 +6586,6 @@
android.Manifest.permission.READ_PHONE_STATE
})
public boolean isIdle() {
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null)
- return telephony.isIdle(getOpPackageName());
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#isIdle", e);
- }
return true;
}
@@ -6782,7 +7000,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- isDataRoamingEnabled = telephony.isDataRoamingEnabled(getSubId());
+ isDataRoamingEnabled = telephony.isDataRoamingEnabled(
+ getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#isDataRoamingEnabled", e);
@@ -6794,7 +7013,7 @@
* Gets the roaming mode for CDMA phone.
*
* <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
- * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+ * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
*
* @return one of {@link #CDMA_ROAMING_MODE_RADIO_DEFAULT}, {@link #CDMA_ROAMING_MODE_HOME},
* {@link #CDMA_ROAMING_MODE_AFFILIATED}, {@link #CDMA_ROAMING_MODE_ANY}.
@@ -6819,7 +7038,7 @@
* Sets the roaming mode for CDMA phone to the given mode {@code mode}.
*
* <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
- * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+ * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
*
* @param mode should be one of {@link #CDMA_ROAMING_MODE_RADIO_DEFAULT},
* {@link #CDMA_ROAMING_MODE_HOME}, {@link #CDMA_ROAMING_MODE_AFFILIATED},
@@ -6888,7 +7107,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- telephony.setDataRoamingEnabled(getSubId(), isEnabled);
+ telephony.setDataRoamingEnabled(
+ getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), isEnabled);
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#setDataRoamingEnabled", e);
@@ -7681,7 +7901,7 @@
* Returns the current {@link ServiceState} information.
*
* <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
- * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+ * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
*
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
@@ -7853,26 +8073,23 @@
}
/**
- * Return the application ID for the app type like {@link APPTYPE_CSIM}.
+ * Return the application ID for the uicc application type like {@link #APPTYPE_CSIM}.
+ * All uicc applications are uniquely identified by application ID. See ETSI 102.221 and 101.220
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE}
*
- * Requires that the calling app has READ_PRIVILEGED_PHONE_STATE permission
- *
- * @param appType the uicc app type like {@link APPTYPE_CSIM}
- * @return Application ID for specificied app type or null if no uicc or error.
+ * @param appType the uicc app type.
+ * @return Application ID for specified app type or {@code null} if no uicc or error.
* @hide
*/
- public String getAidForAppType(int appType) {
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public String getAidForAppType(@UiccAppType int appType) {
return getAidForAppType(getSubId(), appType);
}
/**
- * Return the application ID for the app type like {@link APPTYPE_CSIM}.
- *
- * Requires that the calling app has READ_PRIVILEGED_PHONE_STATE permission
- *
- * @param subId the subscription ID that this request applies to.
- * @param appType the uicc app type, like {@link APPTYPE_CSIM}
- * @return Application ID for specificied app type or null if no uicc or error.
+ * same as {@link #getAidForAppType(int)}
* @hide
*/
public String getAidForAppType(int subId, int appType) {
@@ -8153,7 +8370,7 @@
* Checks if phone is in emergency callback mode.
*
* <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
- * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
+ * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
*
* @return true if phone is in emergency callback mode.
* @hide
@@ -8184,6 +8401,29 @@
}
/**
+ * Checks if manual network selection is allowed.
+ *
+ * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+ * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}.
+ *
+ * @return {@code true} if manual network selection is allowed, otherwise return {@code false}.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ public boolean isManualNetworkSelectionAllowed() {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.isManualNetworkSelectionAllowed(getSubId());
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelephony#isManualNetworkSelectionAllowed", e);
+ }
+ return true;
+ }
+
+ /**
* Get the most recently available signal strength information.
*
* Get the most recent SignalStrength information reported by the modem. Due
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 0e4a7ad..8379f8c 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -31,6 +31,7 @@
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.InetAddress;
@@ -633,33 +634,33 @@
int maxConns, int waitTime, int maxConnsTime, int mtu, int mvnoType,
String mvnoMatchData, int apnSetId) {
return new Builder()
- .setId(id)
- .setOperatorNumeric(operatorNumeric)
- .setEntryName(entryName)
- .setApnName(apnName)
- .setProxyAddress(proxyAddress)
- .setProxyPort(proxyPort)
- .setMmsc(mmsc)
- .setMmsProxyAddress(mmsProxyAddress)
- .setMmsProxyPort(mmsProxyPort)
- .setUser(user)
- .setPassword(password)
- .setAuthType(authType)
- .setApnTypeBitmask(mApnTypeBitmask)
- .setProtocol(protocol)
- .setRoamingProtocol(roamingProtocol)
- .setCarrierEnabled(carrierEnabled)
- .setNetworkTypeBitmask(networkTypeBitmask)
- .setProfileId(profileId)
- .setModemCognitive(modemCognitive)
- .setMaxConns(maxConns)
- .setWaitTime(waitTime)
- .setMaxConnsTime(maxConnsTime)
- .setMtu(mtu)
- .setMvnoType(mvnoType)
- .setMvnoMatchData(mvnoMatchData)
- .setApnSetId(apnSetId)
- .buildWithoutCheck();
+ .setId(id)
+ .setOperatorNumeric(operatorNumeric)
+ .setEntryName(entryName)
+ .setApnName(apnName)
+ .setProxyAddress(proxyAddress)
+ .setProxyPort(proxyPort)
+ .setMmsc(mmsc)
+ .setMmsProxyAddress(mmsProxyAddress)
+ .setMmsProxyPort(mmsProxyPort)
+ .setUser(user)
+ .setPassword(password)
+ .setAuthType(authType)
+ .setApnTypeBitmask(mApnTypeBitmask)
+ .setProtocol(protocol)
+ .setRoamingProtocol(roamingProtocol)
+ .setCarrierEnabled(carrierEnabled)
+ .setNetworkTypeBitmask(networkTypeBitmask)
+ .setProfileId(profileId)
+ .setModemCognitive(modemCognitive)
+ .setMaxConns(maxConns)
+ .setWaitTime(waitTime)
+ .setMaxConnsTime(maxConnsTime)
+ .setMtu(mtu)
+ .setMvnoType(mvnoType)
+ .setMvnoMatchData(mvnoMatchData)
+ .setApnSetId(apnSetId)
+ .buildWithoutCheck();
}
/** @hide */
@@ -691,56 +692,56 @@
}
return makeApnSetting(
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)),
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)),
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)),
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)),
- cursor.getString(
- cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY)),
- portFromString(cursor.getString(
- cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT))),
- UriFromString(cursor.getString(
- cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))),
- cursor.getString(
- cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY)),
- portFromString(cursor.getString(
- cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT))),
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)),
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.AUTH_TYPE)),
- apnTypesBitmask,
- getProtocolIntFromString(
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL))),
- getProtocolIntFromString(
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)),
+ cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY)),
+ portFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT))),
+ UriFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))),
+ cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY)),
+ portFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT))),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.AUTH_TYPE)),
+ apnTypesBitmask,
+ getProtocolIntFromString(
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL))),
+ getProtocolIntFromString(
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.ROAMING_PROTOCOL))),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.CARRIER_ENABLED)) == 1,
+ networkTypeBitmask,
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROFILE_ID)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MODEM_COGNITIVE)) == 1,
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNS)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.WAIT_TIME)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MAX_CONNS_TIME)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU)),
+ getMvnoTypeIntFromString(
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MVNO_TYPE))),
cursor.getString(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.ROAMING_PROTOCOL))),
- cursor.getInt(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.CARRIER_ENABLED)) == 1,
- networkTypeBitmask,
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROFILE_ID)),
- cursor.getInt(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.MODEM_COGNITIVE)) == 1,
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNS)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.WAIT_TIME)),
- cursor.getInt(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.MAX_CONNS_TIME)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU)),
- getMvnoTypeIntFromString(
- cursor.getString(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.MVNO_TYPE))),
- cursor.getString(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.MVNO_MATCH_DATA)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN_SET_ID)));
+ Telephony.Carriers.MVNO_MATCH_DATA)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN_SET_ID)));
}
/** @hide */
public static ApnSetting makeApnSetting(ApnSetting apn) {
return makeApnSetting(apn.mId, apn.mOperatorNumeric, apn.mEntryName, apn.mApnName,
- apn.mProxyAddress, apn.mProxyPort, apn.mMmsc, apn.mMmsProxyAddress,
- apn.mMmsProxyPort, apn.mUser, apn.mPassword, apn.mAuthType, apn.mApnTypeBitmask,
- apn.mProtocol, apn.mRoamingProtocol, apn.mCarrierEnabled, apn.mNetworkTypeBitmask,
- apn.mProfileId, apn.mModemCognitive, apn.mMaxConns, apn.mWaitTime,
- apn.mMaxConnsTime, apn.mMtu, apn.mMvnoType, apn.mMvnoMatchData, apn.mApnSetId);
+ apn.mProxyAddress, apn.mProxyPort, apn.mMmsc, apn.mMmsProxyAddress,
+ apn.mMmsProxyPort, apn.mUser, apn.mPassword, apn.mAuthType, apn.mApnTypeBitmask,
+ apn.mProtocol, apn.mRoamingProtocol, apn.mCarrierEnabled, apn.mNetworkTypeBitmask,
+ apn.mProfileId, apn.mModemCognitive, apn.mMaxConns, apn.mWaitTime,
+ apn.mMaxConnsTime, apn.mMtu, apn.mMvnoType, apn.mMvnoMatchData, apn.mApnSetId);
}
/**
@@ -930,16 +931,16 @@
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[ApnSettingV5] ")
- .append(mEntryName)
- .append(", ").append(mId)
- .append(", ").append(mOperatorNumeric)
- .append(", ").append(mApnName)
- .append(", ").append(mProxyAddress)
- .append(", ").append(UriToString(mMmsc))
- .append(", ").append(mMmsProxyAddress)
- .append(", ").append(portToString(mMmsProxyPort))
- .append(", ").append(portToString(mProxyPort))
- .append(", ").append(mAuthType).append(", ");
+ .append(mEntryName)
+ .append(", ").append(mId)
+ .append(", ").append(mOperatorNumeric)
+ .append(", ").append(mApnName)
+ .append(", ").append(mProxyAddress)
+ .append(", ").append(UriToString(mMmsc))
+ .append(", ").append(mMmsProxyAddress)
+ .append(", ").append(portToString(mMmsProxyPort))
+ .append(", ").append(portToString(mProxyPort))
+ .append(", ").append(mAuthType).append(", ");
final String[] types = getApnTypesStringFromBitmask(mApnTypeBitmask).split(",");
sb.append(TextUtils.join(" | ", types));
sb.append(", ").append(PROTOCOL_INT_MAP.get(mProtocol));
@@ -1021,31 +1022,31 @@
ApnSetting other = (ApnSetting) o;
return mEntryName.equals(other.mEntryName)
- && Objects.equals(mId, other.mId)
- && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
- && Objects.equals(mApnName, other.mApnName)
- && Objects.equals(mProxyAddress, other.mProxyAddress)
- && Objects.equals(mMmsc, other.mMmsc)
- && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
- && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
- && Objects.equals(mProxyPort, other.mProxyPort)
- && Objects.equals(mUser, other.mUser)
- && Objects.equals(mPassword, other.mPassword)
- && Objects.equals(mAuthType, other.mAuthType)
- && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
- && Objects.equals(mProtocol, other.mProtocol)
- && Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
- && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
- && Objects.equals(mProfileId, other.mProfileId)
- && Objects.equals(mModemCognitive, other.mModemCognitive)
- && Objects.equals(mMaxConns, other.mMaxConns)
- && Objects.equals(mWaitTime, other.mWaitTime)
- && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
- && Objects.equals(mMtu, other.mMtu)
- && Objects.equals(mMvnoType, other.mMvnoType)
- && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
- && Objects.equals(mNetworkTypeBitmask, other.mNetworkTypeBitmask)
- && Objects.equals(mApnSetId, other.mApnSetId);
+ && Objects.equals(mId, other.mId)
+ && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+ && Objects.equals(mApnName, other.mApnName)
+ && Objects.equals(mProxyAddress, other.mProxyAddress)
+ && Objects.equals(mMmsc, other.mMmsc)
+ && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
+ && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
+ && Objects.equals(mProxyPort,other.mProxyPort)
+ && Objects.equals(mUser, other.mUser)
+ && Objects.equals(mPassword, other.mPassword)
+ && Objects.equals(mAuthType, other.mAuthType)
+ && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
+ && Objects.equals(mProtocol, other.mProtocol)
+ && Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
+ && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(mProfileId, other.mProfileId)
+ && Objects.equals(mModemCognitive, other.mModemCognitive)
+ && Objects.equals(mMaxConns, other.mMaxConns)
+ && Objects.equals(mWaitTime, other.mWaitTime)
+ && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+ && Objects.equals(mMtu, other.mMtu)
+ && Objects.equals(mMvnoType, other.mMvnoType)
+ && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
+ && Objects.equals(mNetworkTypeBitmask, other.mNetworkTypeBitmask)
+ && Objects.equals(mApnSetId, other.mApnSetId);
}
/**
@@ -1068,29 +1069,29 @@
ApnSetting other = (ApnSetting) o;
return mEntryName.equals(other.mEntryName)
- && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
- && Objects.equals(mApnName, other.mApnName)
- && Objects.equals(mProxyAddress, other.mProxyAddress)
- && Objects.equals(mMmsc, other.mMmsc)
- && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
- && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
- && Objects.equals(mProxyPort, other.mProxyPort)
- && Objects.equals(mUser, other.mUser)
- && Objects.equals(mPassword, other.mPassword)
- && Objects.equals(mAuthType, other.mAuthType)
- && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
- && (isDataRoaming || Objects.equals(mProtocol, other.mProtocol))
- && (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
- && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
- && Objects.equals(mProfileId, other.mProfileId)
- && Objects.equals(mModemCognitive, other.mModemCognitive)
- && Objects.equals(mMaxConns, other.mMaxConns)
- && Objects.equals(mWaitTime, other.mWaitTime)
- && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
- && Objects.equals(mMtu, other.mMtu)
- && Objects.equals(mMvnoType, other.mMvnoType)
- && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
- && Objects.equals(mApnSetId, other.mApnSetId);
+ && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+ && Objects.equals(mApnName, other.mApnName)
+ && Objects.equals(mProxyAddress, other.mProxyAddress)
+ && Objects.equals(mMmsc, other.mMmsc)
+ && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
+ && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
+ && Objects.equals(mProxyPort, other.mProxyPort)
+ && Objects.equals(mUser, other.mUser)
+ && Objects.equals(mPassword, other.mPassword)
+ && Objects.equals(mAuthType, other.mAuthType)
+ && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
+ && (isDataRoaming || Objects.equals(mProtocol,other.mProtocol))
+ && (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
+ && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(mProfileId, other.mProfileId)
+ && Objects.equals(mModemCognitive, other.mModemCognitive)
+ && Objects.equals(mMaxConns, other.mMaxConns)
+ && Objects.equals(mWaitTime, other.mWaitTime)
+ && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+ && Objects.equals(mMtu, other.mMtu)
+ && Objects.equals(mMvnoType, other.mMvnoType)
+ && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
+ && Objects.equals(mApnSetId, other.mApnSetId);
}
/**
@@ -1102,22 +1103,22 @@
*/
public boolean similar(ApnSetting other) {
return (!this.canHandleType(TYPE_DUN)
- && !other.canHandleType(TYPE_DUN)
- && Objects.equals(this.mApnName, other.mApnName)
- && !typeSameAny(this, other)
- && xorEquals(this.mProxyAddress, other.mProxyAddress)
- && xorEqualsInt(this.mProxyPort, other.mProxyPort)
- && xorEquals(this.mProtocol, other.mProtocol)
- && xorEquals(this.mRoamingProtocol, other.mRoamingProtocol)
- && Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
- && Objects.equals(this.mProfileId, other.mProfileId)
- && Objects.equals(this.mMvnoType, other.mMvnoType)
- && Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
- && xorEquals(this.mMmsc, other.mMmsc)
- && xorEquals(this.mMmsProxyAddress, other.mMmsProxyAddress)
- && xorEqualsInt(this.mMmsProxyPort, other.mMmsProxyPort))
- && Objects.equals(this.mNetworkTypeBitmask, other.mNetworkTypeBitmask)
- && Objects.equals(mApnSetId, other.mApnSetId);
+ && !other.canHandleType(TYPE_DUN)
+ && Objects.equals(this.mApnName, other.mApnName)
+ && !typeSameAny(this, other)
+ && xorEquals(this.mProxyAddress, other.mProxyAddress)
+ && xorEqualsInt(this.mProxyPort, other.mProxyPort)
+ && xorEquals(this.mProtocol, other.mProtocol)
+ && xorEquals(this.mRoamingProtocol, other.mRoamingProtocol)
+ && Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(this.mProfileId, other.mProfileId)
+ && Objects.equals(this.mMvnoType, other.mMvnoType)
+ && Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
+ && xorEquals(this.mMmsc, other.mMmsc)
+ && xorEquals(this.mMmsProxyAddress, other.mMmsProxyAddress)
+ && xorEqualsInt(this.mMmsProxyPort, other.mMmsProxyPort))
+ && Objects.equals(this.mNetworkTypeBitmask, other.mNetworkTypeBitmask)
+ && Objects.equals(mApnSetId, other.mApnSetId);
}
// Equal or one is null.
@@ -1205,7 +1206,8 @@
/** @hide */
public static int getMvnoTypeIntFromString(String mvnoType) {
- Integer mvnoTypeInt = MVNO_TYPE_STRING_MAP.get(mvnoType);
+ String mvnoTypeString = TextUtils.isEmpty(mvnoType) ? mvnoType : mvnoType.toLowerCase();
+ Integer mvnoTypeInt = MVNO_TYPE_STRING_MAP.get(mvnoTypeString);
return mvnoTypeInt == null ? UNSPECIFIED_INT : mvnoTypeInt;
}
@@ -1341,13 +1343,13 @@
new Parcelable.Creator<ApnSetting>() {
@Override
public ApnSetting createFromParcel(Parcel in) {
- return readFromParcel(in);
- }
+ return readFromParcel(in);
+ }
@Override
public ApnSetting[] newArray(int size) {
- return new ApnSetting[size];
- }
+ return new ApnSetting[size];
+ }
};
/**
diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.aidl b/telephony/java/android/telephony/emergency/EmergencyNumber.aidl
new file mode 100644
index 0000000..bfb0a59
--- /dev/null
+++ b/telephony/java/android/telephony/emergency/EmergencyNumber.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 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 android.telephony.emergency;
+
+parcelable EmergencyNumber;
diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java
new file mode 100644
index 0000000..d6a08543
--- /dev/null
+++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 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 android.telephony.emergency;
+
+import android.annotation.IntDef;
+import android.hardware.radio.V1_3.EmergencyNumberSource;
+import android.hardware.radio.V1_3.EmergencyServiceCategory;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A parcelable class that wraps and retrieves the information of number, service category(s) and
+ * country code for a specific emergency number.
+ */
+public final class EmergencyNumber implements Parcelable {
+
+ private static final String LOG_TAG = "EmergencyNumber";
+
+ /**
+ * Defining Emergency Service Category as follows:
+ * - General emergency call, all categories;
+ * - Police;
+ * - Ambulance;
+ * - Fire Brigade;
+ * - Marine Guard;
+ * - Mountain Rescue;
+ * - Manually Initiated eCall (MIeC);
+ * - Automatically Initiated eCall (AIeC);
+ *
+ * Category UNSPECIFIED (General emergency call, all categories) indicates that no specific
+ * services are associated with this emergency number; if the emergency number is specified,
+ * it has one or more defined emergency service categories.
+ *
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+ *
+ * @hide
+ */
+ @IntDef(flag = true, prefix = { "EMERGENCY_SERVICE_CATEGORY_" }, value = {
+ EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
+ EMERGENCY_SERVICE_CATEGORY_POLICE,
+ EMERGENCY_SERVICE_CATEGORY_AMBULANCE,
+ EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE,
+ EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD,
+ EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE,
+ EMERGENCY_SERVICE_CATEGORY_MIEC,
+ EMERGENCY_SERVICE_CATEGORY_AIEC
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface EmergencyServiceCategories {}
+
+ /**
+ * Emergency Service Category UNSPECIFIED (General emergency call, all categories) bit-field
+ * indicates that no specific services are associated with this emergency number; if the
+ * emergency number is specified, it has one or more defined emergency service categories.
+ *
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+ */
+ public static final int EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED =
+ EmergencyServiceCategory.UNSPECIFIED;
+ /**
+ * Bit-field that indicates Emergency Service Category for Police.
+ *
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+ */
+ public static final int EMERGENCY_SERVICE_CATEGORY_POLICE = EmergencyServiceCategory.POLICE;
+ /**
+ * Bit-field that indicates Emergency Service Category for Ambulance.
+ *
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+ */
+ public static final int EMERGENCY_SERVICE_CATEGORY_AMBULANCE =
+ EmergencyServiceCategory.AMBULANCE;
+ /**
+ * Bit-field that indicates Emergency Service Category for Fire Brigade.
+ *
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+ */
+ public static final int EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE =
+ EmergencyServiceCategory.FIRE_BRIGADE;
+ /**
+ * Bit-field that indicates Emergency Service Category for Marine Guard.
+ *
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+ */
+ public static final int EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD =
+ EmergencyServiceCategory.MARINE_GUARD;
+ /**
+ * Bit-field that indicates Emergency Service Category for Mountain Rescue.
+ *
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+ */
+ public static final int EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE =
+ EmergencyServiceCategory.MOUNTAIN_RESCUE;
+ /**
+ * Bit-field that indicates Emergency Service Category for Manually Initiated eCall (MIeC)
+ *
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+ */
+ public static final int EMERGENCY_SERVICE_CATEGORY_MIEC = EmergencyServiceCategory.MIEC;
+ /**
+ * Bit-field that indicates Emergency Service Category for Automatically Initiated eCall (AIeC)
+ *
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+ */
+ public static final int EMERGENCY_SERVICE_CATEGORY_AIEC = EmergencyServiceCategory.AIEC;
+
+ private static final Set<Integer> EMERGENCY_SERVICE_CATEGORY_SET;
+ static {
+ EMERGENCY_SERVICE_CATEGORY_SET = new HashSet<Integer>();
+ EMERGENCY_SERVICE_CATEGORY_SET.add(EMERGENCY_SERVICE_CATEGORY_POLICE);
+ EMERGENCY_SERVICE_CATEGORY_SET.add(EMERGENCY_SERVICE_CATEGORY_AMBULANCE);
+ EMERGENCY_SERVICE_CATEGORY_SET.add(EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE);
+ EMERGENCY_SERVICE_CATEGORY_SET.add(EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD);
+ EMERGENCY_SERVICE_CATEGORY_SET.add(EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE);
+ EMERGENCY_SERVICE_CATEGORY_SET.add(EMERGENCY_SERVICE_CATEGORY_MIEC);
+ EMERGENCY_SERVICE_CATEGORY_SET.add(EMERGENCY_SERVICE_CATEGORY_AIEC);
+ }
+
+ /**
+ * The source to tell where the corresponding @1.3::EmergencyNumber comes from.
+ *
+ * The emergency number has one or more defined emergency number sources.
+ *
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+ *
+ * @hide
+ */
+ @IntDef(flag = true, prefix = { "EMERGENCY_NUMBER_SOURCE_" }, value = {
+ EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
+ EMERGENCY_NUMBER_SOURCE_SIM,
+ EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG,
+ EMERGENCY_NUMBER_SOURCE_DEFAULT
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface EmergencyNumberSources {}
+
+ /**
+ * Bit-field which indicates the number is from the network signaling.
+ *
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+ */
+ public static final int EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING =
+ EmergencyNumberSource.NETWORK_SIGNALING;
+ /**
+ * Bit-field which indicates the number is from the sim.
+ *
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+ */
+ public static final int EMERGENCY_NUMBER_SOURCE_SIM = EmergencyNumberSource.SIM;
+ /** Bit-field which indicates the number is from the modem config. */
+ public static final int EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG =
+ EmergencyNumberSource.MODEM_CONFIG;
+ /**
+ * Bit-field which indicates the number is available as default.
+ *
+ * 112, 911 must always be available; additionally, 000, 08, 110, 999, 118 and 119 must be
+ * available when sim is not present.
+ *
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+ */
+ public static final int EMERGENCY_NUMBER_SOURCE_DEFAULT = EmergencyNumberSource.DEFAULT;
+
+ private static final Set<Integer> EMERGENCY_NUMBER_SOURCE_SET;
+ static {
+ EMERGENCY_NUMBER_SOURCE_SET = new HashSet<Integer>();
+ EMERGENCY_NUMBER_SOURCE_SET.add(EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING);
+ EMERGENCY_NUMBER_SOURCE_SET.add(EMERGENCY_NUMBER_SOURCE_SIM);
+ EMERGENCY_NUMBER_SOURCE_SET.add(EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG);
+ EMERGENCY_NUMBER_SOURCE_SET.add(EMERGENCY_NUMBER_SOURCE_DEFAULT);
+ }
+
+ private final String mNumber;
+ private final String mCountryIso;
+ private final int mEmergencyServiceCategoryBitmask;
+ private final int mEmergencyNumberSourceBitmask;
+
+ /** @hide */
+ public EmergencyNumber(String number, String countryIso,
+ int emergencyServiceCategories,
+ int emergencyNumberSources) {
+ this.mNumber = number;
+ this.mCountryIso = countryIso;
+ this.mEmergencyServiceCategoryBitmask = emergencyServiceCategories;
+ this.mEmergencyNumberSourceBitmask = emergencyNumberSources;
+ }
+
+ /** @hide */
+ public EmergencyNumber(Parcel source) {
+ mNumber = source.readString();
+ mCountryIso = source.readString();
+ mEmergencyServiceCategoryBitmask = source.readInt();
+ mEmergencyNumberSourceBitmask = source.readInt();
+ }
+
+ /**
+ * Get the dialing number of the emergency number.
+ *
+ * The character in the number string is only the dial pad
+ * character('0'-'9', '*', or '#'). For example: 911.
+ *
+ * @return the dialing number.
+ */
+ public String getNumber() {
+ return mNumber;
+ }
+
+ /**
+ * Get the country code string (lowercase character) in ISO 3166 format of the emergency number.
+ *
+ * @return the country code string (lowercase character) in ISO 3166 format.
+ */
+ public String getCountryIso() {
+ return mCountryIso;
+ }
+
+ /**
+ * Returns the bitmask of emergency service categories {@link EmergencyServiceCategories} of
+ * the emergency number.
+ *
+ * @return bitmask of the emergency service categories {@link EmergencyServiceCategories}
+ */
+ public @EmergencyServiceCategories int getEmergencyServiceCategoryBitmask() {
+ return mEmergencyServiceCategoryBitmask;
+ }
+
+ /**
+ * Returns the emergency service categories {@link EmergencyServiceCategories} of the emergency
+ * number.
+ *
+ * @return a list of the emergency service categories {@link EmergencyServiceCategories}
+ */
+ public List<Integer> getEmergencyServiceCategories() {
+ List<Integer> categories = new ArrayList<>();
+ if (serviceUnspecified()) {
+ categories.add(EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED);
+ return categories;
+ }
+ for (Integer category : EMERGENCY_SERVICE_CATEGORY_SET) {
+ if (isInEmergencyServiceCategories(category)) {
+ categories.add(category);
+ }
+ }
+ return categories;
+ }
+
+ /**
+ * Checks if the emergency service category is unspecified for the emergency number
+ * {@link #EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED}.
+ *
+ * @return {@code true} if the emergency service category is unspecified for the emergency
+ * number {@link #EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED}; {@code false} otherwise.
+ */
+ private boolean serviceUnspecified() {
+ return mEmergencyServiceCategoryBitmask == EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED;
+ }
+
+ /**
+ * Checks if the emergency number is in the specified emergency service category(s)
+ * {@link EmergencyServiceCategories}.
+ *
+ * @return {@code true} if the emergency number is in the specified emergency service
+ * category(s) {@link EmergencyServiceCategories}; {@code false} otherwise.
+ *
+ * @param categories - emergency service categories {@link EmergencyServiceCategories}
+ */
+ public boolean isInEmergencyServiceCategories(@EmergencyServiceCategories int categories) {
+ if (categories == EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED) {
+ return serviceUnspecified();
+ }
+ return (mEmergencyServiceCategoryBitmask & categories) == categories;
+ }
+
+ /**
+ * Returns the bitmask of the sources {@link EmergencyNumberSources} of the emergency number.
+ *
+ * @return bitmask of the emergency number sources {@link EmergencyNumberSources}
+ */
+ public @EmergencyNumberSources int getEmergencyNumberSourceBitmask() {
+ return mEmergencyNumberSourceBitmask;
+ }
+
+ /**
+ * Returns a list of {@link EmergencyNumberSources} of the emergency number.
+ *
+ * @return a list of {@link EmergencyNumberSources}
+ */
+ public List<Integer> getEmergencyNumberSources() {
+ List<Integer> sources = new ArrayList<>();
+ for (Integer source : EMERGENCY_NUMBER_SOURCE_SET) {
+ if ((mEmergencyNumberSourceBitmask & source) == source) {
+ sources.add(source);
+ }
+ }
+ return sources;
+ }
+
+ /**
+ * Checks if the emergency number is from the specified emergency number source(s)
+ * {@link EmergencyNumberSources}.
+ *
+ * @return {@code true} if the emergency number is from the specified emergency number
+ * source(s) {@link EmergencyNumberSources}; {@code false} otherwise.
+ *
+ * @param sources - {@link EmergencyNumberSources}
+ */
+ public boolean isFromSources(@EmergencyNumberSources int sources) {
+ return (mEmergencyNumberSourceBitmask & sources) == sources;
+ }
+
+ @Override
+ /** @hide */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mNumber);
+ dest.writeString(mCountryIso);
+ dest.writeInt(mEmergencyServiceCategoryBitmask);
+ dest.writeInt(mEmergencyNumberSourceBitmask);
+ }
+
+ @Override
+ /** @hide */
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return "EmergencyNumber = " + "[Number]" + mNumber + " / [CountryIso]" + mCountryIso
+ + " / [ServiceCategories]"
+ + Integer.toBinaryString(mEmergencyServiceCategoryBitmask)
+ + " / [Sources]" + Integer.toBinaryString(mEmergencyNumberSourceBitmask);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!EmergencyNumber.class.isInstance(o)) {
+ return false;
+ }
+ return (o == this || toString().equals(o.toString()));
+ }
+
+ public static final Parcelable.Creator<EmergencyNumber> CREATOR =
+ new Parcelable.Creator<EmergencyNumber>() {
+ @Override
+ public EmergencyNumber createFromParcel(Parcel in) {
+ return new EmergencyNumber(in);
+ }
+
+ @Override
+ public EmergencyNumber[] newArray(int size) {
+ return new EmergencyNumber[size];
+ }
+ };
+}
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index f0d3c89..89ef339 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -117,10 +117,14 @@
* @hide
*/
public static final String EXTRA_CONFERENCE = "conference";
+
/**
- * @hide
+ * Boolean extra property set on an {@link ImsCallProfile} to indicate that this call is an
+ * emergency call. The {@link ImsService} sets this on a call to indicate that the network has
+ * identified the call as an emergency call.
*/
- public static final String EXTRA_E_CALL = "e_call";
+ public static final String EXTRA_EMERGENCY_CALL = "e_call";
+
/**
* @hide
*/
@@ -245,7 +249,8 @@
* constants, the values passed for the {@link #EXTRA_CALL_RAT_TYPE} should be strings (e.g.
* "14" vs (int) 14).
* Note: This is used by {@link com.android.internal.telephony.imsphone.ImsPhoneConnection#
- * updateWifiStateFromExtras(Bundle)} to determine whether to set the
+ * updateImsCallRatFromExtras(Bundle)} to determine whether to set the
+ * {@link android.telecom.TelecomManager#EXTRA_CALL_NETWORK_TYPE} extra value and
* {@link android.telecom.Connection#PROPERTY_WIFI} property on a connection.
*/
public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java
index a20d4f5..df903cc2 100644
--- a/telephony/java/android/telephony/ims/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -16,22 +16,16 @@
package android.telephony.ims;
-import android.annotation.CallbackExecutor;
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
import android.os.Message;
import android.os.RemoteException;
import android.telephony.ims.aidl.IImsCallSessionListener;
-
-import java.util.Objects;
-import java.util.concurrent.Executor;
-
-import android.telephony.ims.stub.ImsCallSessionImplBase;
import android.util.Log;
import com.android.ims.internal.IImsCallSession;
import com.android.ims.internal.IImsVideoCallProvider;
+import java.util.Objects;
+
/**
* Provides the call initiation/termination, and media exchange between two IMS endpoints.
* It directly communicates with IMS service which implements the IMS protocol behavior.
@@ -42,7 +36,8 @@
private static final String TAG = "ImsCallSession";
/**
- * Defines IMS call session state. Please use {@link ImsCallSessionImplBase.State} definition.
+ * Defines IMS call session state. Please use
+ * {@link android.telephony.ims.stub.ImsCallSessionImplBase.State} definition.
* This is kept around for capability reasons.
*/
public static class State {
@@ -1027,9 +1022,9 @@
}
/**
- * Sends RTT Upgrade request
+ * Sends RTT Upgrade or downgrade request
*
- * @param to : expected profile
+ * @param to Profile with the RTT flag set to the desired value
*/
public void sendRttModifyRequest(ImsCallProfile to) {
if (mClosed) {
diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
index 31381804..cecf2e2 100644
--- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
@@ -21,12 +21,11 @@
import android.net.Uri;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.util.Log;
-import android.telephony.ims.ImsReasonInfo;
-
import com.android.internal.annotations.VisibleForTesting;
import java.lang.annotation.Retention;
@@ -81,13 +80,14 @@
* Callback class for receiving Registration callback events.
* @hide
*/
- public static class Callback {
+ public static class Callback extends IImsRegistrationCallback.Stub {
/**
* Notifies the framework when the IMS Provider is connected to the IMS network.
*
* @param imsRadioTech the radio access technology. Valid values are defined in
* {@link ImsRegistrationTech}.
*/
+ @Override
public void onRegistered(@ImsRegistrationTech int imsRadioTech) {
}
@@ -97,6 +97,7 @@
* @param imsRadioTech the radio access technology. Valid values are defined in
* {@link ImsRegistrationTech}.
*/
+ @Override
public void onRegistering(@ImsRegistrationTech int imsRadioTech) {
}
@@ -105,6 +106,7 @@
*
* @param info the {@link ImsReasonInfo} associated with why registration was disconnected.
*/
+ @Override
public void onDeregistered(ImsReasonInfo info) {
}
@@ -115,6 +117,7 @@
* @param imsRadioTech The {@link ImsRegistrationTech} type that has failed
* @param info A {@link ImsReasonInfo} that identifies the reason for failure.
*/
+ @Override
public void onTechnologyChangeFailed(@ImsRegistrationTech int imsRadioTech,
ImsReasonInfo info) {
}
@@ -125,6 +128,7 @@
* @param uris new array of subscriber {@link Uri}s that are associated with this IMS
* subscription.
*/
+ @Override
public void onSubscriberAssociatedUriChanged(Uri[] uris) {
}
diff --git a/telephony/java/android/telephony/mbms/GroupCall.java b/telephony/java/android/telephony/mbms/GroupCall.java
new file mode 100644
index 0000000..9aca18e
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/GroupCall.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 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 android.telephony.mbms;
+
+import android.annotation.IntDef;
+import android.os.RemoteException;
+import android.telephony.MbmsGroupCallSession;
+import android.telephony.mbms.vendor.IMbmsGroupCallService;
+import android.util.Log;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Class used to represent a single MBMS group call. After a call has been started with
+ * {@link MbmsGroupCallSession#startGroupCall},
+ * this class is used to hold information about the call and control it.
+ */
+public class GroupCall implements AutoCloseable {
+ private static final String LOG_TAG = "MbmsGroupCall";
+
+ /**
+ * The state of a group call, reported via
+ * {@link GroupCallCallback#onGroupCallStateChanged(int, int)}
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "STATE_" }, value = {STATE_STOPPED, STATE_STARTED, STATE_STALLED})
+ public @interface GroupCallState {}
+ public static final int STATE_STOPPED = 1;
+ public static final int STATE_STARTED = 2;
+ public static final int STATE_STALLED = 3;
+
+ /**
+ * The reason for a call state change, reported via
+ * {@link GroupCallCallback#onGroupCallStateChanged(int, int)}
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "REASON_" },
+ value = {REASON_BY_USER_REQUEST, REASON_FREQUENCY_CONFLICT,
+ REASON_OUT_OF_MEMORY, REASON_NOT_CONNECTED_TO_HOMECARRIER_LTE,
+ REASON_LEFT_MBMS_BROADCAST_AREA, REASON_NONE})
+ public @interface GroupCallStateChangeReason {}
+
+ /**
+ * Indicates that the middleware does not have a reason to provide for the state change.
+ */
+ public static final int REASON_NONE = 0;
+
+ /**
+ * State changed due to a call to {@link #close()} or
+ * {@link MbmsGroupCallSession#startGroupCall}
+ */
+ public static final int REASON_BY_USER_REQUEST = 1;
+
+ // 2 is unused to match up with streaming.
+
+ /**
+ * State changed due to a frequency conflict with another requested call.
+ */
+ public static final int REASON_FREQUENCY_CONFLICT = 3;
+
+ /**
+ * State changed due to the middleware running out of memory
+ */
+ public static final int REASON_OUT_OF_MEMORY = 4;
+
+ /**
+ * State changed due to the device leaving the home carrier's LTE network.
+ */
+ public static final int REASON_NOT_CONNECTED_TO_HOMECARRIER_LTE = 5;
+
+ /**
+ * State changed due to the device leaving the area where this call is being broadcast.
+ */
+ public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 6;
+
+ private final int mSubscriptionId;
+ private final long mTmgi;
+ private final MbmsGroupCallSession mParentSession;
+ private final InternalGroupCallCallback mCallback;
+ private IMbmsGroupCallService mService;
+
+ /**
+ * @hide
+ */
+ public GroupCall(int subscriptionId,
+ IMbmsGroupCallService service,
+ MbmsGroupCallSession session,
+ long tmgi,
+ InternalGroupCallCallback callback) {
+ mSubscriptionId = subscriptionId;
+ mParentSession = session;
+ mService = service;
+ mTmgi = tmgi;
+ mCallback = callback;
+ }
+
+ /**
+ * Retrieve the TMGI (Temporary Mobile Group Identity) corresponding to this call.
+ */
+ public long getTmgi() {
+ return mTmgi;
+ }
+
+ /**
+ * Send an update to the middleware when the SAI (Service Area Identifier) list and frequency
+ * information of the group call has * changed. Callers must obtain this information from the
+ * wireless carrier independently.
+ * @param saiArray New array of SAIs that the call is available on.
+ * @param frequencyArray New array of frequencies that the call is available on.
+ */
+ public void updateGroupCall(int[] saiArray, int[] frequencyArray) {
+ if (mService == null) {
+ throw new IllegalStateException("No group call service attached");
+ }
+
+ try {
+ mService.updateGroupCall(mSubscriptionId, mTmgi, saiArray, frequencyArray);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Remote process died");
+ mService = null;
+ sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+ } finally {
+ mParentSession.onGroupCallStopped(this);
+ }
+ }
+
+ /**
+ * Stop this group call. Further operations on this object will fail with an
+ * {@link IllegalStateException}.
+ *
+ * May throw an {@link IllegalStateException}
+ */
+ @Override
+ public void close() {
+ if (mService == null) {
+ throw new IllegalStateException("No group call service attached");
+ }
+
+ try {
+ mService.stopGroupCall(mSubscriptionId, mTmgi);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "Remote process died");
+ mService = null;
+ sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+ } finally {
+ mParentSession.onGroupCallStopped(this);
+ }
+ }
+
+ /** @hide */
+ public InternalGroupCallCallback getCallback() {
+ return mCallback;
+ }
+
+ private void sendErrorToApp(int errorCode, String message) {
+ mCallback.onError(errorCode, message);
+ }
+}
+
diff --git a/telephony/java/android/telephony/mbms/GroupCallCallback.java b/telephony/java/android/telephony/mbms/GroupCallCallback.java
new file mode 100644
index 0000000..001bb02
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/GroupCallCallback.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 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 android.telephony.mbms;
+
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A callback class for use when the application is in a group call. The middleware
+ * will provide updates on the status of the call via this callback.
+ */
+public class GroupCallCallback {
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ MbmsErrors.ERROR_NO_UNIQUE_MIDDLEWARE,
+ MbmsErrors.ERROR_MIDDLEWARE_LOST,
+ MbmsErrors.ERROR_MIDDLEWARE_NOT_BOUND,
+ MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_NOT_YET_READY,
+ MbmsErrors.GeneralErrors.ERROR_OUT_OF_MEMORY,
+ MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_TEMPORARILY_UNAVAILABLE,
+ MbmsErrors.GeneralErrors.ERROR_IN_E911,
+ MbmsErrors.GeneralErrors.ERROR_NOT_CONNECTED_TO_HOME_CARRIER_LTE,
+ MbmsErrors.GeneralErrors.ERROR_UNABLE_TO_READ_SIM,
+ MbmsErrors.GeneralErrors.ERROR_CARRIER_CHANGE_NOT_ALLOWED}, prefix = { "ERROR_" })
+ private @interface GroupCallError{}
+
+ /**
+ * Indicates broadcast signal strength is not available for this call.
+ *
+ * This may be due to the call no longer being available due to geography
+ * or timing (end of service)
+ */
+ public static final int SIGNAL_STRENGTH_UNAVAILABLE = -1;
+
+ /**
+ * Called by the middleware when it has detected an error condition in this group call. The
+ * possible error codes are listed in {@link MbmsErrors}.
+ * @param errorCode The error code.
+ * @param message A human-readable message generated by the middleware for debugging purposes.
+ */
+ public void onError(@GroupCallError int errorCode, @Nullable String message) {
+ // default implementation empty
+ }
+
+ /**
+ * Called to indicate this call has changed state.
+ *
+ * See {@link GroupCall#STATE_STOPPED}, {@link GroupCall#STATE_STARTED}
+ * and {@link GroupCall#STATE_STALLED}.
+ */
+ public void onGroupCallStateChanged(@GroupCall.GroupCallState int state,
+ @GroupCall.GroupCallStateChangeReason int reason) {
+ // default implementation empty
+ }
+
+ /**
+ * Broadcast Signal Strength updated.
+ *
+ * This signal strength is the BROADCAST signal strength which,
+ * depending on technology in play and it's deployment, may be
+ * stronger or weaker than the traditional UNICAST signal
+ * strength. It a simple int from 0-4 for valid levels or
+ * {@link #SIGNAL_STRENGTH_UNAVAILABLE} if broadcast is not available
+ * for this call due to timing, geography or popularity.
+ */
+ public void onBroadcastSignalStrengthUpdated(int signalStrength) {
+ // default implementation empty
+ }
+}
diff --git a/telephony/java/android/telephony/mbms/IGroupCallCallback.aidl b/telephony/java/android/telephony/mbms/IGroupCallCallback.aidl
new file mode 100755
index 0000000..844b634
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/IGroupCallCallback.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 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 android.telephony.mbms;
+
+/**
+ * @hide
+ */
+oneway interface IGroupCallCallback {
+ void onError(int errorCode, String message);
+ void onGroupCallStateChanged(int state, int reason);
+ void onBroadcastSignalStrengthUpdated(int signalStrength);
+}
diff --git a/telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl b/telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl
new file mode 100755
index 0000000..1a1c7f8
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl
@@ -0,0 +1,33 @@
+/*
+** 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 android.telephony.mbms;
+
+import java.util.List;
+
+/**
+ * @hide
+ */
+oneway interface IMbmsGroupCallSessionCallback
+{
+ void onError(int errorCode, String message);
+
+ void onAvailableSaisUpdated(in List currentSai, in List availableSais);
+
+ void onServiceInterfaceAvailable(String interfaceName, int index);
+
+ void onMiddlewareReady();
+}
diff --git a/telephony/java/android/telephony/mbms/InternalGroupCallCallback.java b/telephony/java/android/telephony/mbms/InternalGroupCallCallback.java
new file mode 100644
index 0000000..2910bb3
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/InternalGroupCallCallback.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 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 android.telephony.mbms;
+
+import android.os.Binder;
+
+import java.util.concurrent.Executor;
+
+/** @hide */
+public class InternalGroupCallCallback extends IGroupCallCallback.Stub {
+ private final GroupCallCallback mAppCallback;
+ private final Executor mExecutor;
+ private volatile boolean mIsStopped = false;
+
+ public InternalGroupCallCallback(GroupCallCallback appCallback,
+ Executor executor) {
+ mAppCallback = appCallback;
+ mExecutor = executor;
+ }
+
+ @Override
+ public void onError(final int errorCode, final String message) {
+ if (mIsStopped) {
+ return;
+ }
+
+ mExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mAppCallback.onError(errorCode, message);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onGroupCallStateChanged(final int state, final int reason) {
+ if (mIsStopped) {
+ return;
+ }
+
+ mExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mAppCallback.onGroupCallStateChanged(state, reason);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onBroadcastSignalStrengthUpdated(final int signalStrength) {
+ if (mIsStopped) {
+ return;
+ }
+
+ mExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mAppCallback.onBroadcastSignalStrengthUpdated(signalStrength);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ });
+ }
+
+ /** Prevents this callback from calling the app */
+ public void stop() {
+ mIsStopped = true;
+ }
+}
diff --git a/telephony/java/android/telephony/mbms/InternalGroupCallSessionCallback.java b/telephony/java/android/telephony/mbms/InternalGroupCallSessionCallback.java
new file mode 100644
index 0000000..4c9cf4d
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/InternalGroupCallSessionCallback.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 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 android.telephony.mbms;
+
+import android.os.Binder;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/** @hide */
+public class InternalGroupCallSessionCallback extends IMbmsGroupCallSessionCallback.Stub {
+ private final Executor mExecutor;
+ private final MbmsGroupCallSessionCallback mAppCallback;
+ private volatile boolean mIsStopped = false;
+
+ public InternalGroupCallSessionCallback(MbmsGroupCallSessionCallback appCallback,
+ Executor executor) {
+ mAppCallback = appCallback;
+ mExecutor = executor;
+ }
+
+ @Override
+ public void onError(final int errorCode, final String message) {
+ if (mIsStopped) {
+ return;
+ }
+
+ mExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mAppCallback.onError(errorCode, message);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onAvailableSaisUpdated(final List currentSais, final List availableSais) {
+ if (mIsStopped) {
+ return;
+ }
+
+ mExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mAppCallback.onAvailableSaisUpdated(currentSais, availableSais);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onServiceInterfaceAvailable(final String interfaceName, final int index) {
+ if (mIsStopped) {
+ return;
+ }
+
+ mExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mAppCallback.onServiceInterfaceAvailable(interfaceName, index);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onMiddlewareReady() {
+ if (mIsStopped) {
+ return;
+ }
+
+ mExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mAppCallback.onMiddlewareReady();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ });
+ }
+
+ /** Prevents this callback from calling the app */
+ public void stop() {
+ mIsStopped = true;
+ }
+}
diff --git a/telephony/java/android/telephony/mbms/MbmsGroupCallSessionCallback.java b/telephony/java/android/telephony/mbms/MbmsGroupCallSessionCallback.java
new file mode 100644
index 0000000..7da734e
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/MbmsGroupCallSessionCallback.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 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 android.telephony.mbms;
+
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.telephony.MbmsGroupCallSession;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * A callback class that is used to receive information from the middleware on MBMS group-call
+ * services. An instance of this object should be passed into
+ * {@link MbmsGroupCallSession#create(Context, Executor, int, MbmsGroupCallSessionCallback)}.
+ */
+public class MbmsGroupCallSessionCallback {
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ MbmsErrors.ERROR_NO_UNIQUE_MIDDLEWARE,
+ MbmsErrors.ERROR_MIDDLEWARE_LOST,
+ MbmsErrors.ERROR_MIDDLEWARE_NOT_BOUND,
+ MbmsErrors.InitializationErrors.ERROR_APP_PERMISSIONS_NOT_GRANTED,
+ MbmsErrors.InitializationErrors.ERROR_DUPLICATE_INITIALIZE,
+ MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
+ MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_NOT_YET_READY,
+ MbmsErrors.GeneralErrors.ERROR_OUT_OF_MEMORY,
+ MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_TEMPORARILY_UNAVAILABLE,
+ MbmsErrors.GeneralErrors.ERROR_IN_E911,
+ MbmsErrors.GeneralErrors.ERROR_NOT_CONNECTED_TO_HOME_CARRIER_LTE,
+ MbmsErrors.GeneralErrors.ERROR_UNABLE_TO_READ_SIM,
+ MbmsErrors.GeneralErrors.ERROR_CARRIER_CHANGE_NOT_ALLOWED}, prefix = { "ERROR_" })
+ private @interface GroupCallError{}
+
+ /**
+ * Called by the middleware when it has detected an error condition. The possible error codes
+ * are listed in {@link MbmsErrors}.
+ * @param errorCode The error code.
+ * @param message A human-readable message generated by the middleware for debugging purposes.
+ */
+ public void onError(@GroupCallError int errorCode, @Nullable String message) {
+ }
+
+ /**
+ * Indicates that the list of currently available SAIs has been updated. The app may use this
+ * information to filter the list of group calls when displaying available group calls to
+ * the user by matching the SAIs with a list of group calls separately negotiated with the
+ * carrier. The app may also report the aggregate list of SAIs to the group call application
+ * server so that a network entity can determine when, and where to activate the broadcast of
+ * particular group calls.
+ * @param currentSais The available SAIs on the current cell.
+ * @param availableSais A list of lists of available SAIS in neighboring cells, where each list
+ * contains the available SAIs in an individual cell.
+ */
+ public void onAvailableSaisUpdated(List<Integer> currentSais,
+ List<List<Integer>> availableSais) {
+ }
+
+ /**
+ * Called soon after the app calls {@link MbmsGroupCallSession#create}. The information supplied
+ * via this callback may be used to establish a data-link interface with the modem before the
+ * middleware is ready.
+ * Note that this method may be called before {@link #onMiddlewareReady()}.
+ *
+ * @param interfaceName The interface name for the data link.
+ * @param index The index for the data link.
+ */
+ public void onServiceInterfaceAvailable(String interfaceName, int index) {
+ }
+
+ /**
+ * Called to indicate that the middleware has been initialized and is ready.
+ *
+ * Before this method is called, calling any method on an instance of
+ * {@link MbmsGroupCallSession} will result in an {@link IllegalStateException} or an error
+ * delivered via {@link #onError(int, String)} with error code
+ * {@link MbmsErrors.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}.
+ */
+ public void onMiddlewareReady() {
+ }
+}
diff --git a/telephony/java/android/telephony/mbms/MbmsUtils.java b/telephony/java/android/telephony/mbms/MbmsUtils.java
index 06b2120..95b4d37 100644
--- a/telephony/java/android/telephony/mbms/MbmsUtils.java
+++ b/telephony/java/android/telephony/mbms/MbmsUtils.java
@@ -23,6 +23,7 @@
import android.content.pm.*;
import android.content.pm.ServiceInfo;
import android.telephony.MbmsDownloadSession;
+import android.telephony.MbmsGroupCallSession;
import android.telephony.MbmsStreamingSession;
import android.util.Log;
@@ -59,6 +60,9 @@
case MbmsStreamingSession.MBMS_STREAMING_SERVICE_ACTION:
metaDataKey = MbmsStreamingSession.MBMS_STREAMING_SERVICE_OVERRIDE_METADATA;
break;
+ case MbmsGroupCallSession.MBMS_GROUP_CALL_SERVICE_ACTION:
+ metaDataKey = MbmsGroupCallSession.MBMS_GROUP_CALL_SERVICE_OVERRIDE_METADATA;
+ break;
}
if (metaDataKey == null) {
return null;
diff --git a/telephony/java/android/telephony/mbms/vendor/IMbmsGroupCallService.aidl b/telephony/java/android/telephony/mbms/vendor/IMbmsGroupCallService.aidl
new file mode 100755
index 0000000..721256a
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/vendor/IMbmsGroupCallService.aidl
@@ -0,0 +1,39 @@
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.telephony.mbms.vendor;
+
+import android.net.Uri;
+import android.telephony.mbms.IMbmsGroupCallSessionCallback;
+import android.telephony.mbms.IGroupCallCallback;
+
+/**
+ * @hide
+ */
+interface IMbmsGroupCallService
+{
+ int initialize(IMbmsGroupCallSessionCallback callback, int subId);
+
+ void stopGroupCall(int subId, long tmgi);
+
+ void updateGroupCall(int subscriptionId, long tmgi, in int[] saiArray,
+ in int[] frequencyArray);
+
+ int startGroupCall(int subscriptionId, long tmgi, in int[] saiArray,
+ in int[] frequencyArray, IGroupCallCallback callback);
+
+ void dispose(int subId);
+}
diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsGroupCallServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsGroupCallServiceBase.java
new file mode 100644
index 0000000..3734ca7
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/vendor/MbmsGroupCallServiceBase.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 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 android.telephony.mbms.vendor;
+
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.telephony.mbms.GroupCallCallback;
+import android.telephony.mbms.IGroupCallCallback;
+import android.telephony.mbms.IMbmsGroupCallSessionCallback;
+import android.telephony.mbms.MbmsErrors;
+import android.telephony.mbms.MbmsGroupCallSessionCallback;
+import android.telephony.mbms.vendor.IMbmsGroupCallService.Stub;
+
+import java.util.List;
+
+/**
+ * Base class for MBMS group-call services. The middleware should override this class to implement
+ * its {@link Service} for group calls
+ * Subclasses should call this class's {@link #onBind} method to obtain an {@link IBinder} if they
+ * override {@link #onBind}.
+ * @hide
+ */
+@SystemApi
+@TestApi
+public class MbmsGroupCallServiceBase extends Service {
+ private final IBinder mInterface = new Stub() {
+ @Override
+ public int initialize(final IMbmsGroupCallSessionCallback callback,
+ final int subscriptionId) throws RemoteException {
+ if (callback == null) {
+ throw new NullPointerException("Callback must not be null");
+ }
+
+ final int uid = Binder.getCallingUid();
+
+ int result = MbmsGroupCallServiceBase.this.initialize(
+ new MbmsGroupCallSessionCallback() {
+ @Override
+ public void onError(final int errorCode, final String message) {
+ try {
+ if (errorCode == MbmsErrors.UNKNOWN) {
+ throw new IllegalArgumentException(
+ "Middleware cannot send an unknown error.");
+ }
+ callback.onError(errorCode, message);
+ } catch (RemoteException e) {
+ onAppCallbackDied(uid, subscriptionId);
+ }
+ }
+
+ @Override
+ public void onAvailableSaisUpdated(final List currentSais,
+ final List availableSais) {
+ try {
+ callback.onAvailableSaisUpdated(currentSais, availableSais);
+ } catch (RemoteException e) {
+ onAppCallbackDied(uid, subscriptionId);
+ }
+ }
+
+ @Override
+ public void onServiceInterfaceAvailable(final String interfaceName,
+ final int index) {
+ try {
+ callback.onServiceInterfaceAvailable(interfaceName, index);
+ } catch (RemoteException e) {
+ onAppCallbackDied(uid, subscriptionId);
+ }
+ }
+
+ @Override
+ public void onMiddlewareReady() {
+ try {
+ callback.onMiddlewareReady();
+ } catch (RemoteException e) {
+ onAppCallbackDied(uid, subscriptionId);
+ }
+ }
+ }, subscriptionId);
+
+ if (result == MbmsErrors.SUCCESS) {
+ callback.asBinder().linkToDeath(new DeathRecipient() {
+ @Override
+ public void binderDied() {
+ onAppCallbackDied(uid, subscriptionId);
+ }
+ }, 0);
+ }
+
+ return result;
+ }
+
+ @Override
+ public void stopGroupCall(int subId, long tmgi) {
+ MbmsGroupCallServiceBase.this.stopGroupCall(subId, tmgi);
+ }
+
+ @Override
+ public void updateGroupCall(int subscriptionId, long tmgi, int[] saiArray,
+ int[] frequencyArray) {
+ MbmsGroupCallServiceBase.this.updateGroupCall(
+ subscriptionId, tmgi, saiArray, frequencyArray);
+ }
+
+ @Override
+ public int startGroupCall(final int subscriptionId, final long tmgi, final int[] saiArray,
+ final int[] frequencyArray, final IGroupCallCallback callback)
+ throws RemoteException {
+ if (callback == null) {
+ throw new NullPointerException("Callback must not be null");
+ }
+
+ final int uid = Binder.getCallingUid();
+
+ int result = MbmsGroupCallServiceBase.this.startGroupCall(
+ subscriptionId, tmgi, saiArray, frequencyArray, new GroupCallCallback() {
+ @Override
+ public void onError(final int errorCode, final String message) {
+ try {
+ if (errorCode == MbmsErrors.UNKNOWN) {
+ throw new IllegalArgumentException(
+ "Middleware cannot send an unknown error.");
+ }
+ callback.onError(errorCode, message);
+ } catch (RemoteException e) {
+ onAppCallbackDied(uid, subscriptionId);
+ }
+ }
+
+ public void onGroupCallStateChanged(int state, int reason) {
+ try {
+ callback.onGroupCallStateChanged(state, reason);
+ } catch (RemoteException e) {
+ onAppCallbackDied(uid, subscriptionId);
+ }
+ }
+
+ public void onBroadcastSignalStrengthUpdated(int signalStrength) {
+ try {
+ callback.onBroadcastSignalStrengthUpdated(signalStrength);
+ } catch (RemoteException e) {
+ onAppCallbackDied(uid, subscriptionId);
+ }
+ }
+ });
+
+ if (result == MbmsErrors.SUCCESS) {
+ callback.asBinder().linkToDeath(new DeathRecipient() {
+ @Override
+ public void binderDied() {
+ onAppCallbackDied(uid, subscriptionId);
+ }
+ }, 0);
+ }
+
+ return result;
+ }
+
+ @Override
+ public void dispose(int subId) throws RemoteException {
+ MbmsGroupCallServiceBase.this.dispose(subId);
+ }
+ };
+
+ /**
+ * Initialize the group call service for this app and subscription ID, registering the callback.
+ *
+ * May throw an {@link IllegalArgumentException} or a {@link SecurityException}, which
+ * will be intercepted and passed to the app as
+ * {@link MbmsErrors.InitializationErrors#ERROR_UNABLE_TO_INITIALIZE}
+ *
+ * May return any value from {@link MbmsErrors.InitializationErrors}
+ * or {@link MbmsErrors#SUCCESS}. Non-successful error codes will be passed to the app via
+ * {@link IMbmsGroupCallSessionCallback#onError(int, String)}.
+ *
+ * @param callback The callback to use to communicate with the app.
+ * @param subscriptionId The subscription ID to use.
+ */
+ public int initialize(MbmsGroupCallSessionCallback callback, int subscriptionId)
+ throws RemoteException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ /**
+ * Starts a particular group call. This method may perform asynchronous work. When
+ * the call is ready for consumption, the middleware should inform the app via
+ * {@link IGroupCallCallback#onGroupCallStateChanged(int, int)}.
+ *
+ * May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
+ *
+ * @param subscriptionId The subscription id to use.
+ * @param tmgi The TMGI, an identifier for the group call.
+ * @param saiArray An array of SAIs for the group call.
+ * @param frequencyArray An array of frequencies for the group call.
+ * @param callback The callback object on which the app wishes to receive updates.
+ * @return Any error in {@link MbmsErrors.GeneralErrors}
+ */
+ public int startGroupCall(int subscriptionId, long tmgi, int[] saiArray, int[] frequencyArray,
+ GroupCallCallback callback) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ /**
+ * Stop the group call identified by {@code tmgi}.
+ *
+ * The callback provided via {@link #startGroupCall} should no longer be
+ * used after this method has called by the app.
+ *
+ * May throw an {@link IllegalStateException}
+ *
+ * @param subscriptionId The subscription id to use.
+ * @param tmgi The TMGI for the call to stop.
+ */
+ public void stopGroupCall(int subscriptionId, long tmgi) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ /**
+ * Called when the app receives new SAI and frequency information for the group call identified
+ * by {@code tmgi}.
+ * @param saiArray New array of SAIs that the call is available on.
+ * @param frequencyArray New array of frequencies that the call is available on.
+ */
+ public void updateGroupCall(int subscriptionId, long tmgi, int[] saiArray,
+ int[] frequencyArray) {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ /**
+ * Signals that the app wishes to dispose of the session identified by the
+ * {@code subscriptionId} argument and the caller's uid. No notification back to the
+ * app is required for this operation, and the corresponding callback provided via
+ * {@link #initialize} should no longer be used
+ * after this method has been called by the app.
+ *
+ * May throw an {@link IllegalStateException}
+ *
+ * @param subscriptionId The subscription id to use.
+ */
+ public void dispose(int subscriptionId) throws RemoteException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ /**
+ * Indicates that the app identified by the given UID and subscription ID has died.
+ * @param uid the UID of the app, as returned by {@link Binder#getCallingUid()}.
+ * @param subscriptionId The subscription ID the app is using.
+ */
+ public void onAppCallbackDied(int uid, int subscriptionId) {
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mInterface;
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 6521f0b..0ccd748 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -232,5 +232,5 @@
*/
int getSimStateForSlotIndex(int slotIndex);
- boolean isActiveSubId(int subId);
+ boolean isActiveSubId(int subId, String callingPackage);
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 066db1f..ebb94ff 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -75,116 +75,6 @@
void call(String callingPackage, String number);
/**
- * End call if there is a call in progress, otherwise does nothing.
- *
- * @return whether it hung up
- */
- boolean endCall();
-
- /**
- * End call on particular subId or go to the Home screen
- * @param subId user preferred subId.
- * @return whether it hung up
- */
- boolean endCallForSubscriber(int subId);
-
- /**
- * Answer the currently-ringing call.
- *
- * If there's already a current active call, that call will be
- * automatically put on hold. If both lines are currently in use, the
- * current active call will be ended.
- *
- * TODO: provide a flag to let the caller specify what policy to use
- * if both lines are in use. (The current behavior is hardwired to
- * "answer incoming, end ongoing", which is how the CALL button
- * is specced to behave.)
- *
- * TODO: this should be a oneway call (especially since it's called
- * directly from the key queue thread).
- */
- void answerRingingCall();
-
- /**
- * Answer the currently-ringing call on particular subId .
- *
- * If there's already a current active call, that call will be
- * automatically put on hold. If both lines are currently in use, the
- * current active call will be ended.
- *
- * TODO: provide a flag to let the caller specify what policy to use
- * if both lines are in use. (The current behavior is hardwired to
- * "answer incoming, end ongoing", which is how the CALL button
- * is specced to behave.)
- *
- * TODO: this should be a oneway call (especially since it's called
- * directly from the key queue thread).
- */
- void answerRingingCallForSubscriber(int subId);
-
- /**
- * Silence the ringer if an incoming call is currently ringing.
- * (If vibrating, stop the vibrator also.)
- *
- * It's safe to call this if the ringer has already been silenced, or
- * even if there's no incoming call. (If so, this method will do nothing.)
- *
- * TODO: this should be a oneway call too (see above).
- * (Actually *all* the methods here that return void can
- * probably be oneway.)
- */
- void silenceRinger();
-
- /**
- * Check if we are in either an active or holding call
- * @param callingPackage the name of the package making the call.
- * @return true if the phone state is OFFHOOK.
- */
- boolean isOffhook(String callingPackage);
-
- /**
- * Check if a particular subId has an active or holding call
- *
- * @param subId user preferred subId.
- * @param callingPackage the name of the package making the call.
- * @return true if the phone state is OFFHOOK.
- */
- boolean isOffhookForSubscriber(int subId, String callingPackage);
-
- /**
- * Check if an incoming phone call is ringing or call waiting
- * on a particular subId.
- *
- * @param subId user preferred subId.
- * @param callingPackage the name of the package making the call.
- * @return true if the phone state is RINGING.
- */
- boolean isRingingForSubscriber(int subId, String callingPackage);
-
- /**
- * Check if an incoming phone call is ringing or call waiting.
- * @param callingPackage the name of the package making the call.
- * @return true if the phone state is RINGING.
- */
- boolean isRinging(String callingPackage);
-
- /**
- * Check if the phone is idle.
- * @param callingPackage the name of the package making the call.
- * @return true if the phone state is IDLE.
- */
- boolean isIdle(String callingPackage);
-
- /**
- * Check if the phone is idle on a particular subId.
- *
- * @param subId user preferred subId.
- * @param callingPackage the name of the package making the call.
- * @return true if the phone state is IDLE.
- */
- boolean isIdleForSubscriber(int subId, String callingPackage);
-
- /**
* Check to see if the radio is on or not.
* @param callingPackage the name of the package making the call.
* @return returns true if the radio is on.
@@ -817,12 +707,6 @@
IImsConfig getImsConfig(int slotId, int feature);
/**
- * @return true if the IMS resolver is busy resolving a binding and should not be considered
- * available, false if the IMS resolver is idle.
- */
- boolean isResolvingImsBinding();
-
- /**
* @return true if the ImsService to bind to for the slot id specified was set, false otherwise.
*/
boolean setImsService(int slotId, boolean isCarrierImsService, String packageName);
@@ -871,14 +755,15 @@
* Ask the radio to connect to the input network and change selection mode to manual.
*
* @param subId the id of the subscription.
- * @param operatorNumeric the PLMN of the operator to attach to.
- * @param persistSelection Whether the selection will persist until reboot. If true, only allows
+ * @param operatorInfo the operator inforamtion, included the PLMN, long name and short name of
+ * the operator to attach to.
+ * @param persistSelection whether the selection will persist until reboot. If true, only allows
* attaching to the selected PLMN until reboot; otherwise, attach to the chosen PLMN and resume
* normal network selection next time.
- * @return true if the request suceeded.
+ * @return {@code true} on success; {@code true} on any failure.
*/
- boolean setNetworkSelectionModeManual(int subId, in String operatorNumeric,
- boolean persistSelection);
+ boolean setNetworkSelectionModeManual(
+ int subId, in OperatorInfo operatorInfo, boolean persisSelection);
/**
* Set the preferred network type.
@@ -923,6 +808,13 @@
*/
boolean isDataEnabled(int subId);
+ /**
+ * Checks if manual network selection is allowed.
+ *
+ * @return {@code true} if manual network selection is allowed, otherwise return {@code false}.
+ */
+ boolean isManualNetworkSelectionAllowed(int subId);
+
/**
* Get P-CSCF address from PCO after data connection is established or modified.
* @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
diff --git a/telephony/java/com/android/internal/telephony/OperatorInfo.java b/telephony/java/com/android/internal/telephony/OperatorInfo.java
index d0245a0..a47e2b0 100644
--- a/telephony/java/com/android/internal/telephony/OperatorInfo.java
+++ b/telephony/java/com/android/internal/telephony/OperatorInfo.java
@@ -21,7 +21,7 @@
import android.os.Parcelable;
/**
- * {@hide}
+ * @hide
*/
public class OperatorInfo implements Parcelable {
public enum State {
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index f9de776..21f3b92 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -176,6 +176,10 @@
// FIXME: This is used to pass a subId via intents, we need to look at its usage, which is
// FIXME: extensive, and see if this should be an array of all active subId's or ...?
+ /**
+ * @Deprecated use {@link android.telephony.SubscriptionManager#EXTRA_SUBSCRIPTION_INDEX}
+ * instead.
+ */
public static final String SUBSCRIPTION_KEY = "subscription";
public static final String SUB_SETTING = "subSettings";
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
index 6bf22a0..8015b07 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
@@ -33,6 +33,7 @@
import com.android.internal.telephony.SmsConstants;
import java.io.UnsupportedEncodingException;
+import java.util.Locale;
/**
* Parses a GSM or UMTS format SMS-CB message into an {@link SmsCbMessage} object. The class is
@@ -44,16 +45,34 @@
* Languages in the 0000xxxx DCS group as defined in 3GPP TS 23.038, section 5.
*/
private static final String[] LANGUAGE_CODES_GROUP_0 = {
- "de", "en", "it", "fr", "es", "nl", "sv", "da", "pt", "fi", "no", "el", "tr", "hu",
- "pl", null
+ Locale.GERMAN.getLanguage(), // German
+ Locale.ENGLISH.getLanguage(), // English
+ Locale.ITALIAN.getLanguage(), // Italian
+ Locale.FRENCH.getLanguage(), // French
+ new Locale("es").getLanguage(), // Spanish
+ new Locale("nl").getLanguage(), // Dutch
+ new Locale("sv").getLanguage(), // Swedish
+ new Locale("da").getLanguage(), // Danish
+ new Locale("pt").getLanguage(), // Portuguese
+ new Locale("fi").getLanguage(), // Finnish
+ new Locale("nb").getLanguage(), // Norwegian
+ new Locale("el").getLanguage(), // Greek
+ new Locale("tr").getLanguage(), // Turkish
+ new Locale("hu").getLanguage(), // Hungarian
+ new Locale("pl").getLanguage(), // Polish
+ null
};
/**
* Languages in the 0010xxxx DCS group as defined in 3GPP TS 23.038, section 5.
*/
private static final String[] LANGUAGE_CODES_GROUP_2 = {
- "cs", "he", "ar", "ru", "is", null, null, null, null, null, null, null, null, null,
- null, null
+ new Locale("cs").getLanguage(), // Czech
+ new Locale("he").getLanguage(), // Hebrew
+ new Locale("ar").getLanguage(), // Arabic
+ new Locale("ru").getLanguage(), // Russian
+ new Locale("is").getLanguage(), // Icelandic
+ null, null, null, null, null, null, null, null, null, null, null
};
private static final char CARRIAGE_RETURN = 0x0d;
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java b/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java
index 0fabc2f..541ca8d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java
@@ -118,71 +118,103 @@
public static final int MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE
= 0x111E; // 4382
- /** CMAS Message Identifier for Presidential Level alerts for additional languages
- * for additional languages. */
+ /**
+ * CMAS Message Identifier for Presidential Level alerts for additional languages.
+ */
public static final int MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL_LANGUAGE
= 0x111F; // 4383
- /** CMAS Message Identifier for Extreme alerts, Urgency=Immediate, Certainty=Observed
- * for additional languages. */
+ /**
+ * CMAS Message Identifier for Extreme alerts, Urgency=Immediate, Certainty=Observed
+ * for additional languages.
+ */
public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED_LANGUAGE
= 0x1120; // 4384
- /** CMAS Message Identifier for Extreme alerts, Urgency=Immediate, Certainty=Likely
- * for additional languages. */
+ /**
+ * CMAS Message Identifier for Extreme alerts, Urgency=Immediate, Certainty=Likely
+ * for additional languages.
+ */
public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY_LANGUAGE
= 0x1121; // 4385
- /** CMAS Message Identifier for Extreme alerts, Urgency=Expected, Certainty=Observed
- * for additional languages. */
+ /**
+ * CMAS Message Identifier for Extreme alerts, Urgency=Expected, Certainty=Observed
+ * for additional languages.
+ */
public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED_LANGUAGE
= 0x1122; // 4386
- /** CMAS Message Identifier for Extreme alerts, Urgency=Expected, Certainty=Likely
- * for additional languages. */
+ /**
+ * CMAS Message Identifier for Extreme alerts, Urgency=Expected, Certainty=Likely
+ * for additional languages.
+ */
public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY_LANGUAGE
= 0x1123; // 4387
- /** CMAS Message Identifier for Severe alerts, Urgency=Immediate, Certainty=Observed
- * for additional languages. */
+ /**
+ * CMAS Message Identifier for Severe alerts, Urgency=Immediate, Certainty=Observed
+ * for additional languages.
+ */
public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED_LANGUAGE
= 0x1124; // 4388
- /** CMAS Message Identifier for Severe alerts, Urgency=Immediate, Certainty=Likely
- * for additional languages.*/
+ /**
+ * CMAS Message Identifier for Severe alerts, Urgency=Immediate, Certainty=Likely
+ * for additional languages.
+ */
public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY_LANGUAGE
= 0x1125; // 4389
- /** CMAS Message Identifier for Severe alerts, Urgency=Expected, Certainty=Observed
- * for additional languages. */
+ /**
+ * CMAS Message Identifier for Severe alerts, Urgency=Expected, Certainty=Observed
+ * for additional languages.
+ */
public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED_LANGUAGE
= 0x1126; // 4390
- /** CMAS Message Identifier for Severe alerts, Urgency=Expected, Certainty=Likely
- * for additional languages.*/
+ /**
+ * CMAS Message Identifier for Severe alerts, Urgency=Expected, Certainty=Likely
+ * for additional languages.
+ */
public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY_LANGUAGE
= 0x1127; // 4391
- /** CMAS Message Identifier for Child Abduction Emergency (Amber Alert)
- * for additional languages. */
+ /**
+ * CMAS Message Identifier for Child Abduction Emergency (Amber Alert)
+ * for additional languages.
+ */
public static final int MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY_LANGUAGE
= 0x1128; // 4392
- /** CMAS Message Identifier for the Required Monthly Test
- * for additional languages. */
+ /** CMAS Message Identifier for the Required Monthly Test for additional languages. */
public static final int MESSAGE_ID_CMAS_ALERT_REQUIRED_MONTHLY_TEST_LANGUAGE
= 0x1129; // 4393
- /** CMAS Message Identifier for CMAS Exercise
- * for additional languages. */
+ /** CMAS Message Identifier for CMAS Exercise for additional languages. */
public static final int MESSAGE_ID_CMAS_ALERT_EXERCISE_LANGUAGE
= 0x112A; // 4394
- /** CMAS Message Identifier for operator defined use
- * for additional languages. */
+ /** CMAS Message Identifier for operator defined use for additional languages. */
public static final int MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE_LANGUAGE
= 0x112B; // 4395
+ /** CMAS Message Identifier for CMAS Public Safety Alerts. */
+ public static final int MESSAGE_ID_CMAS_ALERT_PUBLIC_SAFETY
+ = 0x112C; // 4396
+
+ /** CMAS Message Identifier for CMAS Public Safety Alerts for additional languages. */
+ public static final int MESSAGE_ID_CMAS_ALERT_PUBLIC_SAFETY_LANGUAGE
+ = 0x112D; // 4397
+
+ /** CMAS Message Identifier for CMAS State/Local Test. */
+ public static final int MESSAGE_ID_CMAS_ALERT_STATE_LOCAL_TEST
+ = 0x112E; // 4398
+
+ /** CMAS Message Identifier for CMAS State/Local Test for additional languages. */
+ public static final int MESSAGE_ID_CMAS_ALERT_STATE_LOCAL_TEST_LANGUAGE
+ = 0x112F; // 4399
+
/** End of CMAS Message Identifier range (including future extensions). */
public static final int MESSAGE_ID_CMAS_LAST_IDENTIFIER
= 0x112F; // 4399
diff --git a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
index 4790b75..6b3df94 100644
--- a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
+++ b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
@@ -93,11 +93,23 @@
* converted. If the array size is more than needed, the rest of array remains unchanged.
*/
public static void bcdToBytes(String bcd, byte[] bytes) {
+ bcdToBytes(bcd, bytes, 0);
+ }
+
+ /**
+ * Converts BCD string to bytes and put it into the given byte array.
+ *
+ * @param bcd This should have an even length. If not, an "0" will be appended to the string.
+ * @param bytes If the array size is less than needed, the rest of the BCD string isn't be
+ * converted. If the array size is more than needed, the rest of array remains unchanged.
+ * @param offset the offset into the bytes[] to fill the data
+ */
+ public static void bcdToBytes(String bcd, byte[] bytes, int offset) {
if (bcd.length() % 2 != 0) {
bcd += "0";
}
- int size = Math.min(bytes.length * 2, bcd.length());
- for (int i = 0, j = 0; i + 1 < size; i += 2, j++) {
+ int size = Math.min((bytes.length - offset) * 2, bcd.length());
+ for (int i = 0, j = offset; i + 1 < size; i += 2, j++) {
bytes[j] = (byte) (charToByte(bcd.charAt(i + 1)) << 4 | charToByte(bcd.charAt(i)));
}
}
@@ -125,6 +137,20 @@
}
/**
+ * Convert a 5 or 6 - digit PLMN string to a nibble-swizzled encoding as per 24.008 10.5.1.3
+ *
+ * @param plmn the PLMN to convert
+ * @param data a byte array for the output
+ * @param offset the offset into data to start writing
+ */
+ public static void stringToBcdPlmn(final String plmn, byte[] data, int offset) {
+ char digit6 = (plmn.length() > 5) ? plmn.charAt(5) : 'F';
+ data[offset] = (byte) (charToByte(plmn.charAt(1)) << 4 | charToByte(plmn.charAt(0)));
+ data[offset + 1] = (byte) (charToByte(digit6) << 4 | charToByte(plmn.charAt(2)));
+ data[offset + 2] = (byte) (charToByte(plmn.charAt(4)) << 4 | charToByte(plmn.charAt(3)));
+ }
+
+ /**
* Some fields (like ICC ID) in GSM SIMs are stored as nibble-swizzled BCH
*/
public static String
@@ -844,7 +870,7 @@
}
/**
- * Converts a character of [0-9a-aA-F] to its hex value in a byte. If the character is not a
+ * Converts a character of [0-9a-fA-F] to its hex value in a byte. If the character is not a
* hex number, 0 will be returned.
*/
private static byte charToByte(char c) {
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 6ce66f0..639ed7d 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -245,8 +245,14 @@
mIterationCycle = false;
// In the "applaunch.txt" file, trail launches is referenced using
// "TRIAL_LAUNCH"
- String appPkgName = mNameToIntent.get(launch.getApp())
- .getComponent().getPackageName();
+ Intent startIntent = mNameToIntent.get(launch.getApp());
+ if (startIntent == null) {
+ Log.w(TAG, "App does not exist: " + launch.getApp());
+ mResult.putString(mNameToResultKey.get(launch.getApp()),
+ "App does not exist");
+ continue;
+ }
+ String appPkgName = startIntent.getComponent().getPackageName();
if (SPEED_PROFILE_FILTER.equals(launch.getCompilerFilter())) {
assertTrue(String.format("Not able to compile the app : %s", appPkgName),
compileApp(VERIFY_FILTER, appPkgName));
diff --git a/tests/DexLoggerIntegrationTests/AndroidManifest.xml b/tests/DexLoggerIntegrationTests/AndroidManifest.xml
index a847e8f..a9f01ed 100644
--- a/tests/DexLoggerIntegrationTests/AndroidManifest.xml
+++ b/tests/DexLoggerIntegrationTests/AndroidManifest.xml
@@ -17,10 +17,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.frameworks.dexloggertest">
- <!-- Tests feature introduced in P (27) -->
+ <!-- Tests feature introduced in P (28) -->
<uses-sdk
- android:minSdkVersion="27"
- android:targetSdkVersion="27" />
+ android:minSdkVersion="28"
+ android:targetSdkVersion="28" />
<uses-permission android:name="android.permission.READ_LOGS" />
diff --git a/tests/NetworkSecurityConfigTest/Android.mk b/tests/NetworkSecurityConfigTest/Android.mk
index fe65ecc..c225e17 100644
--- a/tests/NetworkSecurityConfigTest/Android.mk
+++ b/tests/NetworkSecurityConfigTest/Android.mk
@@ -7,7 +7,6 @@
LOCAL_JAVA_LIBRARIES := \
android.test.runner \
- bouncycastle \
conscrypt \
android.test.base \
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
index e529b93..750e2fb 100644
--- a/tests/net/Android.mk
+++ b/tests/net/Android.mk
@@ -38,6 +38,7 @@
libbacktrace \
libbase \
libbinder \
+ libbinderthreadstate \
libc++ \
libcrypto \
libcutils \
diff --git a/tests/net/AndroidManifest.xml b/tests/net/AndroidManifest.xml
index ba1a2ea..6dae3f1 100644
--- a/tests/net/AndroidManifest.xml
+++ b/tests/net/AndroidManifest.xml
@@ -44,6 +44,7 @@
<uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" />
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
+ <uses-permission android:name="android.permission.NETWORK_STACK" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/tests/net/java/android/net/dhcp/DhcpPacketTest.java b/tests/net/java/android/net/dhcp/DhcpPacketTest.java
index 312b3d1..a592809 100644
--- a/tests/net/java/android/net/dhcp/DhcpPacketTest.java
+++ b/tests/net/java/android/net/dhcp/DhcpPacketTest.java
@@ -25,6 +25,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.annotation.Nullable;
import android.net.DhcpResults;
import android.net.LinkAddress;
import android.net.NetworkUtils;
@@ -37,6 +38,7 @@
import java.io.ByteArrayOutputStream;
import java.net.Inet4Address;
import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -56,6 +58,8 @@
private static final Inet4Address NETMASK = getPrefixMaskAsInet4Address(PREFIX_LENGTH);
private static final Inet4Address BROADCAST_ADDR = getBroadcastAddress(
SERVER_ADDR, PREFIX_LENGTH);
+ private static final String HOSTNAME = "testhostname";
+ private static final short MTU = 1500;
// Use our own empty address instead of Inet4Address.ANY or INADDR_ANY to ensure that the code
// doesn't use == instead of equals when comparing addresses.
private static final Inet4Address ANY = (Inet4Address) v4Address("0.0.0.0");
@@ -960,7 +964,8 @@
assertTrue(msg, Arrays.equals(expected, actual));
}
- public void checkBuildOfferPacket(int leaseTimeSecs) throws Exception {
+ public void checkBuildOfferPacket(int leaseTimeSecs, @Nullable String hostname)
+ throws Exception {
final int renewalTime = (int) (Integer.toUnsignedLong(leaseTimeSecs) / 2);
final int rebindingTime = (int) (Integer.toUnsignedLong(leaseTimeSecs) * 875 / 1000);
final int transactionId = 0xdeadbeef;
@@ -971,7 +976,8 @@
CLIENT_MAC, leaseTimeSecs, NETMASK /* netMask */,
BROADCAST_ADDR /* bcAddr */, Collections.singletonList(SERVER_ADDR) /* gateways */,
Collections.singletonList(SERVER_ADDR) /* dnsServers */,
- SERVER_ADDR /* dhcpServerIdentifier */, null /* domainName */, false /* metered */);
+ SERVER_ADDR /* dhcpServerIdentifier */, null /* domainName */, hostname,
+ false /* metered */, MTU);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
// BOOTP headers
@@ -1027,12 +1033,22 @@
// Nameserver
bos.write(new byte[] { (byte) 0x06, (byte) 0x04 });
bos.write(SERVER_ADDR.getAddress());
+ // Hostname
+ if (hostname != null) {
+ bos.write(new byte[]{(byte) 0x0c, (byte) hostname.length()});
+ bos.write(hostname.getBytes(Charset.forName("US-ASCII")));
+ }
+ // MTU
+ bos.write(new byte[] { (byte) 0x1a, (byte) 0x02 });
+ bos.write(shortToByteArray(MTU));
// End options.
bos.write(0xff);
- final byte[] expected = bos.toByteArray();
- assertTrue((expected.length & 1) == 0);
+ if ((bos.size() & 1) != 0) {
+ bos.write(0x00);
+ }
+ final byte[] expected = bos.toByteArray();
final byte[] actual = new byte[packet.limit()];
packet.get(actual);
final String msg = "Expected:\n " + HexDump.dumpHexString(expected) +
@@ -1042,13 +1058,18 @@
@Test
public void testOfferPacket() throws Exception {
- checkBuildOfferPacket(3600);
- checkBuildOfferPacket(Integer.MAX_VALUE);
- checkBuildOfferPacket(0x80000000);
- checkBuildOfferPacket(INFINITE_LEASE);
+ checkBuildOfferPacket(3600, HOSTNAME);
+ checkBuildOfferPacket(Integer.MAX_VALUE, HOSTNAME);
+ checkBuildOfferPacket(0x80000000, HOSTNAME);
+ checkBuildOfferPacket(INFINITE_LEASE, HOSTNAME);
+ checkBuildOfferPacket(3600, null);
}
private static byte[] intToByteArray(int val) {
return ByteBuffer.allocate(4).putInt(val).array();
}
+
+ private static byte[] shortToByteArray(short val) {
+ return ByteBuffer.allocate(2).putShort(val).array();
+ }
}
diff --git a/tests/net/java/android/net/dhcp/DhcpServerTest.java b/tests/net/java/android/net/dhcp/DhcpServerTest.java
index 45a50d9..df34c73 100644
--- a/tests/net/java/android/net/dhcp/DhcpServerTest.java
+++ b/tests/net/java/android/net/dhcp/DhcpServerTest.java
@@ -17,6 +17,7 @@
package android.net.dhcp;
import static android.net.dhcp.DhcpPacket.DHCP_CLIENT;
+import static android.net.dhcp.DhcpPacket.DHCP_HOST_NAME;
import static android.net.dhcp.DhcpPacket.ENCAP_BOOTP;
import static android.net.dhcp.DhcpPacket.INADDR_ANY;
import static android.net.dhcp.DhcpPacket.INADDR_BROADCAST;
@@ -87,6 +88,7 @@
Arrays.asList(parseAddr("192.168.0.200"), parseAddr("192.168.0.201")));
private static final long TEST_LEASE_TIME_SECS = 3600L;
private static final int TEST_MTU = 1500;
+ private static final String TEST_HOSTNAME = "testhostname";
private static final int TEST_TRANSACTION_ID = 123;
private static final byte[] TEST_CLIENT_MAC_BYTES = new byte [] { 1, 2, 3, 4, 5, 6 };
@@ -96,7 +98,10 @@
private static final long TEST_CLOCK_TIME = 1234L;
private static final int TEST_LEASE_EXPTIME_SECS = 3600;
private static final DhcpLease TEST_LEASE = new DhcpLease(null, TEST_CLIENT_MAC,
- TEST_CLIENT_ADDR, TEST_LEASE_EXPTIME_SECS*1000L + TEST_CLOCK_TIME, null /* hostname */);
+ TEST_CLIENT_ADDR, TEST_LEASE_EXPTIME_SECS * 1000L + TEST_CLOCK_TIME,
+ null /* hostname */);
+ private static final DhcpLease TEST_LEASE_WITH_HOSTNAME = new DhcpLease(null, TEST_CLIENT_MAC,
+ TEST_CLIENT_ADDR, TEST_LEASE_EXPTIME_SECS * 1000L + TEST_CLOCK_TIME, TEST_HOSTNAME);
@NonNull @Mock
private Dependencies mDeps;
@@ -217,15 +222,17 @@
public void testRequest_Selecting_Ack() throws Exception {
when(mRepository.requestLease(isNull() /* clientId */, eq(TEST_CLIENT_MAC),
eq(INADDR_ANY) /* clientAddr */, eq(INADDR_ANY) /* relayAddr */,
- eq(TEST_CLIENT_ADDR) /* reqAddr */, eq(true) /* sidSet */, isNull() /* hostname */))
- .thenReturn(TEST_LEASE);
+ eq(TEST_CLIENT_ADDR) /* reqAddr */, eq(true) /* sidSet */, eq(TEST_HOSTNAME)))
+ .thenReturn(TEST_LEASE_WITH_HOSTNAME);
final DhcpRequestPacket request = makeRequestSelectingPacket();
+ request.mHostName = TEST_HOSTNAME;
+ request.mRequestedParams = new byte[] { DHCP_HOST_NAME };
mServer.processPacket(request, DHCP_CLIENT);
assertResponseSentTo(TEST_CLIENT_ADDR);
final DhcpAckPacket packet = assertAck(getPacket());
- assertMatchesTestLease(packet);
+ assertMatchesTestLease(packet, TEST_HOSTNAME);
}
@Test
@@ -270,14 +277,18 @@
* - other request states (init-reboot/renewing/rebinding)
*/
- private void assertMatchesTestLease(@NonNull DhcpPacket packet) {
+ private void assertMatchesTestLease(@NonNull DhcpPacket packet, @Nullable String hostname) {
assertMatchesClient(packet);
assertFalse(packet.hasExplicitClientId());
assertEquals(TEST_SERVER_ADDR, packet.mServerIdentifier);
assertEquals(TEST_CLIENT_ADDR, packet.mYourIp);
assertNotNull(packet.mLeaseTime);
assertEquals(TEST_LEASE_EXPTIME_SECS, (int) packet.mLeaseTime);
- assertNull(packet.mHostName);
+ assertEquals(hostname, packet.mHostName);
+ }
+
+ private void assertMatchesTestLease(@NonNull DhcpPacket packet) {
+ assertMatchesTestLease(packet, null);
}
private void assertMatchesClient(@NonNull DhcpPacket packet) {
diff --git a/tests/net/java/android/net/netlink/InetDiagSocketTest.java b/tests/net/java/android/net/netlink/InetDiagSocketTest.java
new file mode 100644
index 0000000..122edba
--- /dev/null
+++ b/tests/net/java/android/net/netlink/InetDiagSocketTest.java
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 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 android.net.netlink;
+
+import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
+import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
+import static android.os.Process.INVALID_UID;
+import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.AF_INET6;
+import static android.system.OsConstants.IPPROTO_TCP;
+import static android.system.OsConstants.IPPROTO_UDP;
+import static android.system.OsConstants.SOCK_DGRAM;
+import static android.system.OsConstants.SOCK_STREAM;
+import static android.system.OsConstants.SOL_SOCKET;
+import static android.system.OsConstants.SO_RCVTIMEO;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.netlink.StructNlMsgHdr;
+import android.os.Process;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.filters.SmallTest;
+import android.support.test.InstrumentationRegistry;
+import android.system.Os;
+import android.system.StructTimeval;
+import android.util.Log;
+import java.io.FileDescriptor;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import libcore.util.HexEncoding;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class InetDiagSocketTest {
+ private final String TAG = "InetDiagSocketTest";
+ private ConnectivityManager mCm;
+ private Context mContext;
+ private final static int SOCKET_TIMEOUT_MS = 100;
+
+ @Before
+ public void setUp() throws Exception {
+ Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+ mContext = instrumentation.getTargetContext();
+ mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ }
+
+ private class Connection {
+ public int socketDomain;
+ public int socketType;
+ public InetAddress localAddress;
+ public InetAddress remoteAddress;
+ public InetAddress localhostAddress;
+ public InetSocketAddress local;
+ public InetSocketAddress remote;
+ public int protocol;
+ public FileDescriptor localFd;
+ public FileDescriptor remoteFd;
+
+ public FileDescriptor createSocket() throws Exception {
+ return Os.socket(socketDomain, socketType, protocol);
+ }
+
+ public Connection(String to, String from) throws Exception {
+ remoteAddress = InetAddress.getByName(to);
+ if (from != null) {
+ localAddress = InetAddress.getByName(from);
+ } else {
+ localAddress = (remoteAddress instanceof Inet4Address) ?
+ Inet4Address.getByName("localhost") : Inet6Address.getByName("::");
+ }
+ if ((localAddress instanceof Inet4Address) && (remoteAddress instanceof Inet4Address)) {
+ socketDomain = AF_INET;
+ localhostAddress = Inet4Address.getByName("localhost");
+ } else {
+ socketDomain = AF_INET6;
+ localhostAddress = Inet6Address.getByName("::");
+ }
+ }
+
+ public void close() throws Exception {
+ Os.close(localFd);
+ }
+ }
+
+ private class TcpConnection extends Connection {
+ public TcpConnection(String to, String from) throws Exception {
+ super(to, from);
+ protocol = IPPROTO_TCP;
+ socketType = SOCK_STREAM;
+
+ remoteFd = createSocket();
+ Os.bind(remoteFd, remoteAddress, 0);
+ Os.listen(remoteFd, 10);
+ int remotePort = ((InetSocketAddress) Os.getsockname(remoteFd)).getPort();
+
+ localFd = createSocket();
+ Os.bind(localFd, localAddress, 0);
+ Os.connect(localFd, remoteAddress, remotePort);
+
+ local = (InetSocketAddress) Os.getsockname(localFd);
+ remote = (InetSocketAddress) Os.getpeername(localFd);
+ }
+
+ public void close() throws Exception {
+ super.close();
+ Os.close(remoteFd);
+ }
+ }
+ private class UdpConnection extends Connection {
+ public UdpConnection(String to, String from) throws Exception {
+ super(to, from);
+ protocol = IPPROTO_UDP;
+ socketType = SOCK_DGRAM;
+
+ remoteFd = null;
+ localFd = createSocket();
+ Os.bind(localFd, localAddress, 0);
+
+ Os.connect(localFd, remoteAddress, 7);
+ local = (InetSocketAddress) Os.getsockname(localFd);
+ remote = new InetSocketAddress(remoteAddress, 7);
+ }
+ }
+
+ private void checkConnectionOwnerUid(int protocol, InetSocketAddress local,
+ InetSocketAddress remote, boolean expectSuccess) {
+ final int expectedUid = expectSuccess ? Process.myUid() : INVALID_UID;
+ final int uid = mCm.getConnectionOwnerUid(protocol, local, remote);
+ assertEquals(expectedUid, uid);
+ }
+
+ private int findLikelyFreeUdpPort(UdpConnection conn) throws Exception {
+ UdpConnection udp = new UdpConnection(conn.remoteAddress.getHostAddress(),
+ conn.localAddress.getHostAddress());
+ final int localPort = udp.local.getPort();
+ udp.close();
+ return localPort;
+ }
+
+ public void checkGetConnectionOwnerUid(String to, String from) throws Exception {
+ /**
+ * For TCP connections, create a test connection and verify that this
+ * {protocol, local, remote} socket result in receiving a valid UID.
+ */
+ TcpConnection tcp = new TcpConnection(to, from);
+ checkConnectionOwnerUid(tcp.protocol, tcp.local, tcp.remote, true);
+ checkConnectionOwnerUid(IPPROTO_UDP, tcp.local, tcp.remote, false);
+ checkConnectionOwnerUid(tcp.protocol, new InetSocketAddress(0), tcp.remote, false);
+ checkConnectionOwnerUid(tcp.protocol, tcp.local, new InetSocketAddress(0), false);
+ tcp.close();
+
+ /**
+ * For UDP connections, either a complete match {protocol, local, remote} or a
+ * partial match {protocol, local} should return a valid UID.
+ */
+ UdpConnection udp = new UdpConnection(to,from);
+ checkConnectionOwnerUid(udp.protocol, udp.local, udp.remote, true);
+ checkConnectionOwnerUid(udp.protocol, udp.local, new InetSocketAddress(0), true);
+ checkConnectionOwnerUid(IPPROTO_TCP, udp.local, udp.remote, false);
+ checkConnectionOwnerUid(udp.protocol, new InetSocketAddress(findLikelyFreeUdpPort(udp)),
+ udp.remote, false);
+ udp.close();
+ }
+
+ @Test
+ public void testGetConnectionOwnerUid() throws Exception {
+ checkGetConnectionOwnerUid("::", null);
+ checkGetConnectionOwnerUid("::", "::");
+ checkGetConnectionOwnerUid("0.0.0.0", null);
+ checkGetConnectionOwnerUid("0.0.0.0", "0.0.0.0");
+ checkGetConnectionOwnerUid("127.0.0.1", null);
+ checkGetConnectionOwnerUid("127.0.0.1", "127.0.0.2");
+ checkGetConnectionOwnerUid("::1", null);
+ checkGetConnectionOwnerUid("::1", "::1");
+ }
+
+ // Hexadecimal representation of InetDiagReqV2 request.
+ private static final String INET_DIAG_REQ_V2_UDP_INET4_HEX =
+ // struct nlmsghdr
+ "48000000" + // length = 72
+ "1400" + // type = SOCK_DIAG_BY_FAMILY
+ "0103" + // flags = NLM_F_REQUEST | NLM_F_DUMP
+ "00000000" + // seqno
+ "00000000" + // pid (0 == kernel)
+ // struct inet_diag_req_v2
+ "02" + // family = AF_INET
+ "11" + // protcol = IPPROTO_UDP
+ "00" + // idiag_ext
+ "00" + // pad
+ "ffffffff" + // idiag_states
+ // inet_diag_sockid
+ "a5de" + // idiag_sport = 42462
+ "b971" + // idiag_dport = 47473
+ "0a006402000000000000000000000000" + // idiag_src = 10.0.100.2
+ "08080808000000000000000000000000" + // idiag_dst = 8.8.8.8
+ "00000000" + // idiag_if
+ "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE
+ private static final byte[] INET_DIAG_REQ_V2_UDP_INET4_BYTES =
+ HexEncoding.decode(INET_DIAG_REQ_V2_UDP_INET4_HEX.toCharArray(), false);
+
+ @Test
+ public void testInetDiagReqV2UdpInet4() throws Exception {
+ InetSocketAddress local = new InetSocketAddress(InetAddress.getByName("10.0.100.2"),
+ 42462);
+ InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"),
+ 47473);
+ final byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_UDP, local, remote, AF_INET,
+ (short) (NLM_F_REQUEST | NLM_F_DUMP));
+ assertArrayEquals(INET_DIAG_REQ_V2_UDP_INET4_BYTES, msg);
+ }
+
+ // Hexadecimal representation of InetDiagReqV2 request.
+ private static final String INET_DIAG_REQ_V2_TCP_INET6_HEX =
+ // struct nlmsghdr
+ "48000000" + // length = 72
+ "1400" + // type = SOCK_DIAG_BY_FAMILY
+ "0100" + // flags = NLM_F_REQUEST
+ "00000000" + // seqno
+ "00000000" + // pid (0 == kernel)
+ // struct inet_diag_req_v2
+ "0a" + // family = AF_INET6
+ "06" + // protcol = IPPROTO_TCP
+ "00" + // idiag_ext
+ "00" + // pad
+ "ffffffff" + // idiag_states
+ // inet_diag_sockid
+ "a5de" + // idiag_sport = 42462
+ "b971" + // idiag_dport = 47473
+ "fe8000000000000086c9b2fffe6aed4b" + // idiag_src = fe80::86c9:b2ff:fe6a:ed4b
+ "08080808000000000000000000000000" + // idiag_dst = 8.8.8.8
+ "00000000" + // idiag_if
+ "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE
+ private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_BYTES =
+ HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_HEX.toCharArray(), false);
+
+ @Test
+ public void testInetDiagReqV2TcpInet6() throws Exception {
+ InetSocketAddress local = new InetSocketAddress(
+ InetAddress.getByName("fe80::86c9:b2ff:fe6a:ed4b"), 42462);
+ InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"),
+ 47473);
+ byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET6,
+ NLM_F_REQUEST);
+
+ assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg);
+ }
+
+ // Hexadecimal representation of InetDiagReqV2 request.
+ private static final String INET_DIAG_MSG_HEX =
+ // struct nlmsghdr
+ "58000000" + // length = 88
+ "1400" + // type = SOCK_DIAG_BY_FAMILY
+ "0200" + // flags = NLM_F_MULTI
+ "00000000" + // seqno
+ "f5220000" + // pid (0 == kernel)
+ // struct inet_diag_msg
+ "0a" + // family = AF_INET6
+ "01" + // idiag_state
+ "00" + // idiag_timer
+ "00" + // idiag_retrans
+ // inet_diag_sockid
+ "a817" + // idiag_sport = 43031
+ "960f" + // idiag_dport = 38415
+ "fe8000000000000086c9b2fffe6aed4b" + // idiag_src = fe80::86c9:b2ff:fe6a:ed4b
+ "00000000000000000000ffff08080808" + // idiag_dst = 8.8.8.8
+ "00000000" + // idiag_if
+ "ffffffffffffffff" + // idiag_cookie = INET_DIAG_NOCOOKIE
+ "00000000" + // idiag_expires
+ "00000000" + // idiag_rqueue
+ "00000000" + // idiag_wqueue
+ "a3270000" + // idiag_uid
+ "A57E1900"; // idiag_inode
+ private static final byte[] INET_DIAG_MSG_BYTES =
+ HexEncoding.decode(INET_DIAG_MSG_HEX.toCharArray(), false);
+
+ @Test
+ public void testParseInetDiagResponse() throws Exception {
+ final ByteBuffer byteBuffer = ByteBuffer.wrap(INET_DIAG_MSG_BYTES);
+ byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
+ final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer);
+ assertNotNull(msg);
+
+ assertTrue(msg instanceof InetDiagMessage);
+ final InetDiagMessage inetDiagMsg = (InetDiagMessage) msg;
+ assertEquals(10147, inetDiagMsg.mStructInetDiagMsg.idiag_uid);
+
+ final StructNlMsgHdr hdr = inetDiagMsg.getHeader();
+ assertNotNull(hdr);
+ assertEquals(NetlinkConstants.SOCK_DIAG_BY_FAMILY, hdr.nlmsg_type);
+ assertEquals(StructNlMsgHdr.NLM_F_MULTI, hdr.nlmsg_flags);
+ assertEquals(0, hdr.nlmsg_seq);
+ assertEquals(8949, hdr.nlmsg_pid);
+ }
+}
diff --git a/tests/net/java/android/net/util/SharedLogTest.java b/tests/net/java/android/net/util/SharedLogTest.java
index d46facf..8604860 100644
--- a/tests/net/java/android/net/util/SharedLogTest.java
+++ b/tests/net/java/android/net/util/SharedLogTest.java
@@ -44,6 +44,8 @@
final SharedLog logLevel2a = logTop.forSubComponent("twoA");
final SharedLog logLevel2b = logTop.forSubComponent("twoB");
logLevel2b.e("2b or not 2b");
+ logLevel2b.e("No exception", null);
+ logLevel2b.e("Wait, here's one", new Exception("Test"));
logLevel2a.w("second post?");
final SharedLog logLevel3 = logLevel2a.forSubComponent("three");
@@ -54,6 +56,9 @@
final String[] expected = {
" - MARK first post!",
" - [twoB] ERROR 2b or not 2b",
+ " - [twoB] ERROR No exception",
+ // No stacktrace in shared log, only in logcat
+ " - [twoB] ERROR Wait, here's one: Test",
" - [twoA] WARN second post?",
" - still logging",
" - [twoA.three] 3 >> 2",
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index e3db7e8..1c77fcc 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -79,6 +79,7 @@
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
+import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -248,7 +249,7 @@
@Spy private Resources mResources;
private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
- MockContext(Context base) {
+ MockContext(Context base, ContentProvider settingsProvider) {
super(base);
mResources = spy(base.getResources());
@@ -260,7 +261,7 @@
});
mContentResolver = new MockContentResolver();
- mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+ mContentResolver.addProvider(Settings.AUTHORITY, settingsProvider);
}
@Override
@@ -1048,7 +1049,9 @@
Looper.prepare();
}
- mServiceContext = new MockContext(InstrumentationRegistry.getContext());
+ FakeSettingsProvider.clearSettingsProvider();
+ mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
+ new FakeSettingsProvider());
LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
LocalServices.addService(
NetworkPolicyManagerInternal.class, mock(NetworkPolicyManagerInternal.class));
@@ -1067,13 +1070,13 @@
// Ensure that the default setting for Captive Portals is used for most tests
setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
- setMobileDataAlwaysOn(false);
+ setAlwaysOnNetworks(false);
setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
}
@After
public void tearDown() throws Exception {
- setMobileDataAlwaysOn(false);
+ setAlwaysOnNetworks(false);
if (mCellNetworkAgent != null) {
mCellNetworkAgent.disconnect();
mCellNetworkAgent = null;
@@ -1086,6 +1089,7 @@
mEthernetNetworkAgent.disconnect();
mEthernetNetworkAgent = null;
}
+ FakeSettingsProvider.clearSettingsProvider();
}
private static int transportToLegacyType(int transport) {
@@ -2023,7 +2027,7 @@
@Test
public void testNetworkGoesIntoBackgroundAfterLinger() {
- setMobileDataAlwaysOn(true);
+ setAlwaysOnNetworks(true);
NetworkRequest request = new NetworkRequest.Builder()
.clearCapabilities()
.build();
@@ -2768,10 +2772,10 @@
Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
}
- private void setMobileDataAlwaysOn(boolean enable) {
+ private void setAlwaysOnNetworks(boolean enable) {
ContentResolver cr = mServiceContext.getContentResolver();
Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
- mService.updateMobileDataAlwaysOn();
+ mService.updateAlwaysOnNetworks();
waitForIdle();
}
@@ -2793,7 +2797,7 @@
public void testBackgroundNetworks() throws Exception {
// Create a background request. We can't do this ourselves because ConnectivityService
// doesn't have an API for it. So just turn on mobile data always on.
- setMobileDataAlwaysOn(true);
+ setAlwaysOnNetworks(true);
final NetworkRequest request = new NetworkRequest.Builder().build();
final NetworkRequest fgRequest = new NetworkRequest.Builder()
.addCapability(NET_CAPABILITY_FOREGROUND).build();
@@ -2991,7 +2995,7 @@
// Turn on mobile data always on. The factory starts looking again.
testFactory.expectAddRequests(1);
- setMobileDataAlwaysOn(true);
+ setAlwaysOnNetworks(true);
testFactory.waitForNetworkRequests(2);
assertTrue(testFactory.getMyStartRequested());
@@ -3011,7 +3015,7 @@
// Turn off mobile data always on and expect the request to disappear...
testFactory.expectRemoveRequests(1);
- setMobileDataAlwaysOn(false);
+ setAlwaysOnNetworks(false);
testFactory.waitForNetworkRequests(1);
// ... and cell data to be torn down.
@@ -4532,4 +4536,78 @@
mCellNetworkAgent.disconnect();
mCm.unregisterNetworkCallback(networkCallback);
}
+
+ @Test
+ public void testDataActivityTracking() throws RemoteException {
+ final TestNetworkCallback networkCallback = new TestNetworkCallback();
+ final NetworkRequest networkRequest = new NetworkRequest.Builder()
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .build();
+ mCm.registerNetworkCallback(networkRequest, networkCallback);
+
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ final LinkProperties cellLp = new LinkProperties();
+ cellLp.setInterfaceName(MOBILE_IFNAME);
+ mCellNetworkAgent.sendLinkProperties(cellLp);
+ reset(mNetworkManagementService);
+ mCellNetworkAgent.connect(true);
+ networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
+ eq(ConnectivityManager.TYPE_MOBILE));
+
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ final LinkProperties wifiLp = new LinkProperties();
+ wifiLp.setInterfaceName(WIFI_IFNAME);
+ mWiFiNetworkAgent.sendLinkProperties(wifiLp);
+
+ // Network switch
+ reset(mNetworkManagementService);
+ mWiFiNetworkAgent.connect(true);
+ networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+ verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
+ eq(ConnectivityManager.TYPE_WIFI));
+ verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
+
+ // Disconnect wifi and switch back to cell
+ reset(mNetworkManagementService);
+ mWiFiNetworkAgent.disconnect();
+ networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ assertNoCallbacks(networkCallback);
+ verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
+ verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
+ eq(ConnectivityManager.TYPE_MOBILE));
+
+ // reconnect wifi
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ wifiLp.setInterfaceName(WIFI_IFNAME);
+ mWiFiNetworkAgent.sendLinkProperties(wifiLp);
+ mWiFiNetworkAgent.connect(true);
+ networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+
+ // Disconnect cell
+ reset(mNetworkManagementService);
+ mCellNetworkAgent.disconnect();
+ networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ // LOST callback is triggered earlier than removing idle timer. Broadcast should also be
+ // sent as network being switched. Ensure rule removal for cell will not be triggered
+ // unexpectedly before network being removed.
+ waitForIdle();
+ verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
+ verify(mNetworkManagementService, times(1)).removeNetwork(
+ eq(mCellNetworkAgent.getNetwork().netId));
+
+ // Disconnect wifi
+ ConditionVariable cv = waitForConnectivityBroadcasts(1);
+ reset(mNetworkManagementService);
+ mWiFiNetworkAgent.disconnect();
+ waitFor(cv);
+ verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
+
+ // Clean up
+ mCm.unregisterNetworkCallback(networkCallback);
+ }
}
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index 99a5a69..9b919abf 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -16,6 +16,8 @@
package com.android.server;
+import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.AF_INET6;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
@@ -34,8 +36,10 @@
import android.net.IpSecConfig;
import android.net.IpSecManager;
import android.net.IpSecSpiResponse;
+import android.net.IpSecTransform;
import android.net.IpSecTransformResponse;
import android.net.IpSecTunnelInterfaceResponse;
+import android.net.IpSecUdpEncapResponse;
import android.net.LinkAddress;
import android.net.Network;
import android.net.NetworkUtils;
@@ -62,16 +66,17 @@
private static final int TEST_SPI = 0xD1201D;
- private final String mDestinationAddr;
private final String mSourceAddr;
+ private final String mDestinationAddr;
private final LinkAddress mLocalInnerAddress;
+ private final int mFamily;
@Parameterized.Parameters
public static Collection ipSecConfigs() {
return Arrays.asList(
new Object[][] {
- {"1.2.3.4", "8.8.4.4", "10.0.1.1/24"},
- {"2601::2", "2601::10", "2001:db8::1/64"}
+ {"1.2.3.4", "8.8.4.4", "10.0.1.1/24", AF_INET},
+ {"2601::2", "2601::10", "2001:db8::1/64", AF_INET6}
});
}
@@ -129,12 +134,14 @@
new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
private static final IpSecAlgorithm AEAD_ALGO =
new IpSecAlgorithm(IpSecAlgorithm.AUTH_CRYPT_AES_GCM, AEAD_KEY, 128);
+ private static final int REMOTE_ENCAP_PORT = 4500;
public IpSecServiceParameterizedTest(
- String sourceAddr, String destAddr, String localInnerAddr) {
+ String sourceAddr, String destAddr, String localInnerAddr, int family) {
mSourceAddr = sourceAddr;
mDestinationAddr = destAddr;
mLocalInnerAddress = new LinkAddress(localInnerAddr);
+ mFamily = family;
}
@Before
@@ -157,6 +164,8 @@
.thenReturn(AppOpsManager.MODE_IGNORED);
}
+ //TODO: Add a test to verify SPI.
+
@Test
public void testIpSecServiceReserveSpi() throws Exception {
when(mMockNetd.ipSecAllocateSpi(anyInt(), anyString(), eq(mDestinationAddr), eq(TEST_SPI)))
@@ -257,6 +266,47 @@
config.setAuthentication(AUTH_ALGO);
}
+ private void addEncapSocketToIpSecConfig(int resourceId, IpSecConfig config) throws Exception {
+ config.setEncapType(IpSecTransform.ENCAP_ESPINUDP);
+ config.setEncapSocketResourceId(resourceId);
+ config.setEncapRemotePort(REMOTE_ENCAP_PORT);
+ }
+
+ private void verifyTransformNetdCalledForCreatingSA(
+ IpSecConfig config, IpSecTransformResponse resp) throws Exception {
+ verifyTransformNetdCalledForCreatingSA(config, resp, 0);
+ }
+
+ private void verifyTransformNetdCalledForCreatingSA(
+ IpSecConfig config, IpSecTransformResponse resp, int encapSocketPort) throws Exception {
+ IpSecAlgorithm auth = config.getAuthentication();
+ IpSecAlgorithm crypt = config.getEncryption();
+ IpSecAlgorithm authCrypt = config.getAuthenticatedEncryption();
+
+ verify(mMockNetd, times(1))
+ .ipSecAddSecurityAssociation(
+ eq(mUid),
+ eq(config.getMode()),
+ eq(config.getSourceAddress()),
+ eq(config.getDestinationAddress()),
+ eq((config.getNetwork() != null) ? config.getNetwork().netId : 0),
+ eq(TEST_SPI),
+ eq(0),
+ eq(0),
+ eq((auth != null) ? auth.getName() : ""),
+ eq((auth != null) ? auth.getKey() : new byte[] {}),
+ eq((auth != null) ? auth.getTruncationLengthBits() : 0),
+ eq((crypt != null) ? crypt.getName() : ""),
+ eq((crypt != null) ? crypt.getKey() : new byte[] {}),
+ eq((crypt != null) ? crypt.getTruncationLengthBits() : 0),
+ eq((authCrypt != null) ? authCrypt.getName() : ""),
+ eq((authCrypt != null) ? authCrypt.getKey() : new byte[] {}),
+ eq((authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0),
+ eq(config.getEncapType()),
+ eq(encapSocketPort),
+ eq(config.getEncapRemotePort()));
+ }
+
@Test
public void testCreateTransform() throws Exception {
IpSecConfig ipSecConfig = new IpSecConfig();
@@ -267,28 +317,7 @@
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
assertEquals(IpSecManager.Status.OK, createTransformResp.status);
- verify(mMockNetd)
- .ipSecAddSecurityAssociation(
- eq(mUid),
- anyInt(),
- anyString(),
- anyString(),
- anyInt(),
- eq(TEST_SPI),
- anyInt(),
- anyInt(),
- eq(IpSecAlgorithm.AUTH_HMAC_SHA256),
- eq(AUTH_KEY),
- anyInt(),
- eq(IpSecAlgorithm.CRYPT_AES_CBC),
- eq(CRYPT_KEY),
- anyInt(),
- eq(""),
- eq(new byte[] {}),
- eq(0),
- anyInt(),
- anyInt(),
- anyInt());
+ verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
}
@Test
@@ -302,28 +331,59 @@
mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
assertEquals(IpSecManager.Status.OK, createTransformResp.status);
- verify(mMockNetd)
- .ipSecAddSecurityAssociation(
- eq(mUid),
- anyInt(),
- anyString(),
- anyString(),
- anyInt(),
- eq(TEST_SPI),
- anyInt(),
- anyInt(),
- eq(""),
- eq(new byte[] {}),
- eq(0),
- eq(""),
- eq(new byte[] {}),
- eq(0),
- eq(IpSecAlgorithm.AUTH_CRYPT_AES_GCM),
- eq(AEAD_KEY),
- anyInt(),
- anyInt(),
- anyInt(),
- anyInt());
+ verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp);
+ }
+
+ @Test
+ public void testCreateTransportModeTransformWithEncap() throws Exception {
+ IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder());
+
+ IpSecConfig ipSecConfig = new IpSecConfig();
+ ipSecConfig.setMode(IpSecTransform.MODE_TRANSPORT);
+ addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
+ addAuthAndCryptToIpSecConfig(ipSecConfig);
+ addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig);
+
+ if (mFamily == AF_INET) {
+ IpSecTransformResponse createTransformResp =
+ mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
+ assertEquals(IpSecManager.Status.OK, createTransformResp.status);
+
+ verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port);
+ } else {
+ try {
+ IpSecTransformResponse createTransformResp =
+ mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
+ fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+ }
+
+ @Test
+ public void testCreateTunnelModeTransformWithEncap() throws Exception {
+ IpSecUdpEncapResponse udpSock = mIpSecService.openUdpEncapsulationSocket(0, new Binder());
+
+ IpSecConfig ipSecConfig = new IpSecConfig();
+ ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL);
+ addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
+ addAuthAndCryptToIpSecConfig(ipSecConfig);
+ addEncapSocketToIpSecConfig(udpSock.resourceId, ipSecConfig);
+
+ if (mFamily == AF_INET) {
+ IpSecTransformResponse createTransformResp =
+ mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
+ assertEquals(IpSecManager.Status.OK, createTransformResp.status);
+
+ verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp, udpSock.port);
+ } else {
+ try {
+ IpSecTransformResponse createTransformResp =
+ mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage");
+ fail("Expected IllegalArgumentException on attempt to use UDP Encap in IPv6");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
}
@Test
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index 40d5544..a6ed9f2 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -33,6 +33,7 @@
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
+import static android.provider.Settings.Global.TETHER_ENABLE_LEGACY_DHCP_SERVER;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -75,6 +76,8 @@
import android.net.NetworkState;
import android.net.NetworkUtils;
import android.net.RouteInfo;
+import android.net.dhcp.DhcpServer;
+import android.net.dhcp.DhcpServingParams;
import android.net.ip.IpServer;
import android.net.ip.RouterAdvertisementDaemon;
import android.net.util.InterfaceParams;
@@ -85,6 +88,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.INetworkManagementService;
+import android.os.Looper;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.test.TestLooper;
@@ -146,6 +150,7 @@
@Mock private UpstreamNetworkMonitor mUpstreamNetworkMonitor;
@Mock private IPv6TetheringCoordinator mIPv6TetheringCoordinator;
@Mock private RouterAdvertisementDaemon mRouterAdvertisementDaemon;
+ @Mock private DhcpServer mDhcpServer;
@Mock private INetd mNetd;
private final MockTetheringDependencies mTetheringDependencies =
@@ -240,6 +245,12 @@
public INetd getNetdService() {
return mNetd;
}
+
+ @Override
+ public DhcpServer makeDhcpServer(Looper looper, InterfaceParams iface,
+ DhcpServingParams params, SharedLog log) {
+ return mDhcpServer;
+ }
};
}
@@ -333,6 +344,7 @@
mServiceContext = new MockContext(mContext);
mContentResolver = new MockContentResolver(mServiceContext);
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+ Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 0);
mIntents = new Vector<>();
mBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -343,12 +355,16 @@
mServiceContext.registerReceiver(mBroadcastReceiver,
new IntentFilter(ACTION_TETHER_STATE_CHANGED));
mTetheringDependencies.reset();
- mTethering = new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
- mLooper.getLooper(), mSystemProperties,
- mTetheringDependencies);
+ mTethering = makeTethering();
verify(mNMService).registerTetheringStatsProvider(any(), anyString());
}
+ private Tethering makeTethering() {
+ return new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
+ mLooper.getLooper(), mSystemProperties,
+ mTetheringDependencies);
+ }
+
@After
public void tearDown() {
mServiceContext.unregisterReceiver(mBroadcastReceiver);
@@ -597,6 +613,18 @@
sendIPv6TetherUpdates(upstreamState);
verify(mRouterAdvertisementDaemon, never()).buildNewRa(any(), notNull());
+ verify(mDhcpServer, times(1)).start();
+ }
+
+ @Test
+ public void workingMobileUsbTethering_IPv4LegacyDhcp() {
+ Settings.Global.putInt(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, 1);
+ mTethering = makeTethering();
+ final NetworkState upstreamState = buildMobileIPv4UpstreamState();
+ runUsbTethering(upstreamState);
+ sendIPv6TetherUpdates(upstreamState);
+
+ verify(mDhcpServer, never()).start();
}
@Test
@@ -620,6 +648,7 @@
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
verify(mRouterAdvertisementDaemon, times(1)).start();
+ verify(mDhcpServer, times(1)).start();
sendIPv6TetherUpdates(upstreamState);
verify(mRouterAdvertisementDaemon, times(1)).buildNewRa(any(), notNull());
@@ -633,6 +662,7 @@
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_XLAT_MOBILE_IFNAME);
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mDhcpServer, times(1)).start();
verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME,
TEST_XLAT_MOBILE_IFNAME);
@@ -649,6 +679,7 @@
runUsbTethering(upstreamState);
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ verify(mDhcpServer, times(1)).start();
verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
// Then 464xlat comes up
@@ -671,6 +702,8 @@
// Forwarding was not re-added for v6 (still times(1))
verify(mNMService, times(1)).enableNat(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
verify(mNMService, times(1)).startInterfaceForwarding(TEST_USB_IFNAME, TEST_MOBILE_IFNAME);
+ // DHCP not restarted on downstream (still times(1))
+ verify(mDhcpServer, times(1)).start();
}
@Test
diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
index bb31230..5217784 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
@@ -225,13 +225,4 @@
final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog);
assertFalse(cfg.enableLegacyDhcpServer);
}
-
- @Test
- public void testNewDhcpServerDefault() {
- Settings.Global.putString(mContentResolver, TETHER_ENABLE_LEGACY_DHCP_SERVER, null);
-
- final TetheringConfiguration cfg = new TetheringConfiguration(mMockContext, mLog);
- // TODO: change to false when new server is promoted to default
- assertTrue(cfg.enableLegacyDhcpServer);
- }
}
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index 48cfc44..750fb56 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -120,7 +120,6 @@
"util/BigBuffer.cpp",
"util/Files.cpp",
"util/Util.cpp",
- "ConfigDescription.cpp",
"Debug.cpp",
"DominatorTree.cpp",
"Flags.cpp",
@@ -130,7 +129,6 @@
"java/ManifestClassGenerator.cpp",
"java/ProguardRules.cpp",
"LoadedApk.cpp",
- "Locale.cpp",
"Resource.cpp",
"ResourceParser.cpp",
"ResourceTable.cpp",
diff --git a/tools/aapt2/DominatorTree.cpp b/tools/aapt2/DominatorTree.cpp
index 118a385..ff18033 100644
--- a/tools/aapt2/DominatorTree.cpp
+++ b/tools/aapt2/DominatorTree.cpp
@@ -19,8 +19,9 @@
#include <algorithm>
#include "android-base/logging.h"
+#include "androidfw/ConfigDescription.h"
-#include "ConfigDescription.h"
+using ::android::ConfigDescription;
namespace aapt {
diff --git a/tools/aapt2/DominatorTree_test.cpp b/tools/aapt2/DominatorTree_test.cpp
index efc523f..fe4f951 100644
--- a/tools/aapt2/DominatorTree_test.cpp
+++ b/tools/aapt2/DominatorTree_test.cpp
@@ -23,6 +23,8 @@
#include "test/Test.h"
#include "util/Util.h"
+using ::android::ConfigDescription;
+
namespace aapt {
namespace {
diff --git a/tools/aapt2/OWNERS b/tools/aapt2/OWNERS
index 23ec5ab..f1903a5 100644
--- a/tools/aapt2/OWNERS
+++ b/tools/aapt2/OWNERS
@@ -1,2 +1,3 @@
set noparent
toddke@google.com
+rtmitchell@google.com
\ No newline at end of file
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 6fcf0f6..1c1aedd 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -24,10 +24,10 @@
#include <tuple>
#include <vector>
+#include "androidfw/ConfigDescription.h"
#include "androidfw/StringPiece.h"
#include "utils/JenkinsHash.h"
-#include "ConfigDescription.h"
#include "Source.h"
namespace aapt {
@@ -171,7 +171,7 @@
ResourceName name;
// Configuration
- ConfigDescription config;
+ android::ConfigDescription config;
// Type
Type type;
@@ -189,7 +189,7 @@
*/
struct ResourceKey {
ResourceName name;
- ConfigDescription config;
+ android::ConfigDescription config;
};
bool operator<(const ResourceKey& a, const ResourceKey& b);
@@ -201,16 +201,16 @@
*/
struct ResourceKeyRef {
ResourceNameRef name;
- ConfigDescription config;
+ android::ConfigDescription config;
ResourceKeyRef() = default;
- ResourceKeyRef(const ResourceNameRef& n, const ConfigDescription& c)
+ ResourceKeyRef(const ResourceNameRef& n, const android::ConfigDescription& c)
: name(n), config(c) {}
/**
* Prevent taking a reference to a temporary. This is bad.
*/
- ResourceKeyRef(ResourceName&& n, const ConfigDescription& c) = delete;
+ ResourceKeyRef(ResourceName&& n, const android::ConfigDescription& c) = delete;
};
bool operator<(const ResourceKeyRef& a, const ResourceKeyRef& b);
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 7f48544..39ca80b 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -34,6 +34,7 @@
using ::aapt::ResourceUtils::StringBuilder;
using ::aapt::text::Utf8Iterator;
+using ::android::ConfigDescription;
using ::android::StringPiece;
namespace aapt {
diff --git a/tools/aapt2/ResourceParser.h b/tools/aapt2/ResourceParser.h
index fb9dbd0..6cc7b76 100644
--- a/tools/aapt2/ResourceParser.h
+++ b/tools/aapt2/ResourceParser.h
@@ -20,9 +20,9 @@
#include <memory>
#include "android-base/macros.h"
+#include "androidfw/ConfigDescription.h"
#include "androidfw/StringPiece.h"
-#include "ConfigDescription.h"
#include "Diagnostics.h"
#include "ResourceTable.h"
#include "ResourceValues.h"
@@ -53,7 +53,7 @@
class ResourceParser {
public:
ResourceParser(IDiagnostics* diag, ResourceTable* table, const Source& source,
- const ConfigDescription& config,
+ const android::ConfigDescription& config,
const ResourceParserOptions& options = {});
bool Parse(xml::XmlPullParser* parser);
@@ -110,7 +110,7 @@
IDiagnostics* diag_;
ResourceTable* table_;
Source source_;
- ConfigDescription config_;
+ android::ConfigDescription config_;
ResourceParserOptions options_;
};
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 41b4041..9de43c0 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -29,6 +29,7 @@
using ::aapt::io::StringInputStream;
using ::aapt::test::StrValueEq;
using ::aapt::test::ValueEq;
+using ::android::ConfigDescription;
using ::android::Res_value;
using ::android::ResTable_map;
using ::android::StringPiece;
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index d0faac3..c2274d0 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -23,9 +23,9 @@
#include "android-base/logging.h"
#include "android-base/stringprintf.h"
+#include "androidfw/ConfigDescription.h"
#include "androidfw/ResourceTypes.h"
-#include "ConfigDescription.h"
#include "NameMangler.h"
#include "ResourceValues.h"
#include "ValueVisitor.h"
@@ -33,6 +33,7 @@
#include "util/Util.h"
using ::aapt::text::IsValidResourceEntryName;
+using ::android::ConfigDescription;
using ::android::StringPiece;
using ::android::base::StringPrintf;
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index 8534eaa..7b19a31 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -17,7 +17,6 @@
#ifndef AAPT_RESOURCE_TABLE_H
#define AAPT_RESOURCE_TABLE_H
-#include "ConfigDescription.h"
#include "Diagnostics.h"
#include "Resource.h"
#include "ResourceValues.h"
@@ -26,6 +25,7 @@
#include "io/File.h"
#include "android-base/macros.h"
+#include "androidfw/ConfigDescription.h"
#include "androidfw/StringPiece.h"
#include <functional>
@@ -66,7 +66,7 @@
class ResourceConfigValue {
public:
// The configuration for which this value is defined.
- const ConfigDescription config;
+ const android::ConfigDescription config;
// The product for which this value is defined.
const std::string product;
@@ -74,7 +74,7 @@
// The actual Value.
std::unique_ptr<Value> value;
- ResourceConfigValue(const ConfigDescription& config, const android::StringPiece& product)
+ ResourceConfigValue(const android::ConfigDescription& config, const android::StringPiece& product)
: config(config), product(product.to_string()) {}
private:
@@ -103,14 +103,14 @@
explicit ResourceEntry(const android::StringPiece& name) : name(name.to_string()) {}
- ResourceConfigValue* FindValue(const ConfigDescription& config);
+ ResourceConfigValue* FindValue(const android::ConfigDescription& config);
- ResourceConfigValue* FindValue(const ConfigDescription& config,
+ ResourceConfigValue* FindValue(const android::ConfigDescription& config,
const android::StringPiece& product);
- ResourceConfigValue* FindOrCreateValue(const ConfigDescription& config,
+ ResourceConfigValue* FindOrCreateValue(const android::ConfigDescription& config,
const android::StringPiece& product);
- std::vector<ResourceConfigValue*> FindAllValues(const ConfigDescription& config);
+ std::vector<ResourceConfigValue*> FindAllValues(const android::ConfigDescription& config);
template <typename Func>
std::vector<ResourceConfigValue*> FindValuesIf(Func f) {
@@ -182,29 +182,30 @@
// When a collision of resources occurs, this method decides which value to keep.
static CollisionResult ResolveValueCollision(Value* existing, Value* incoming);
- bool AddResource(const ResourceNameRef& name, const ConfigDescription& config,
+ bool AddResource(const ResourceNameRef& name, const android::ConfigDescription& config,
const android::StringPiece& product, std::unique_ptr<Value> value,
IDiagnostics* diag);
bool AddResourceWithId(const ResourceNameRef& name, const ResourceId& res_id,
- const ConfigDescription& config, const android::StringPiece& product,
- std::unique_ptr<Value> value, IDiagnostics* diag);
+ const android::ConfigDescription& config,
+ const android::StringPiece& product, std::unique_ptr<Value> value,
+ IDiagnostics* diag);
- bool AddFileReference(const ResourceNameRef& name, const ConfigDescription& config,
+ bool AddFileReference(const ResourceNameRef& name, const android::ConfigDescription& config,
const Source& source, const android::StringPiece& path, IDiagnostics* diag);
- bool AddFileReferenceMangled(const ResourceNameRef& name, const ConfigDescription& config,
+ bool AddFileReferenceMangled(const ResourceNameRef& name, const android::ConfigDescription& config,
const Source& source, const android::StringPiece& path,
io::IFile* file, IDiagnostics* diag);
// Same as AddResource, but doesn't verify the validity of the name. This is used
// when loading resources from an existing binary resource table that may have mangled names.
- bool AddResourceMangled(const ResourceNameRef& name, const ConfigDescription& config,
+ bool AddResourceMangled(const ResourceNameRef& name, const android::ConfigDescription& config,
const android::StringPiece& product, std::unique_ptr<Value> value,
IDiagnostics* diag);
bool AddResourceWithIdMangled(const ResourceNameRef& name, const ResourceId& id,
- const ConfigDescription& config,
+ const android::ConfigDescription& config,
const android::StringPiece& product, std::unique_ptr<Value> value,
IDiagnostics* diag);
@@ -277,11 +278,12 @@
IDiagnostics* diag);
bool AddResourceImpl(const ResourceNameRef& name, const ResourceId& res_id,
- const ConfigDescription& config, const android::StringPiece& product,
- std::unique_ptr<Value> value, NameValidator name_validator,
- const CollisionResolverFunc& conflict_resolver, IDiagnostics* diag);
+ const android::ConfigDescription& config,
+ const android::StringPiece& product, std::unique_ptr<Value> value,
+ NameValidator name_validator, const CollisionResolverFunc& conflict_resolver,
+ IDiagnostics* diag);
- bool AddFileReferenceImpl(const ResourceNameRef& name, const ConfigDescription& config,
+ bool AddFileReferenceImpl(const ResourceNameRef& name, const android::ConfigDescription& config,
const Source& source, const android::StringPiece& path, io::IFile* file,
NameValidator name_validator, IDiagnostics* diag);
diff --git a/tools/aapt2/ResourceTable_test.cpp b/tools/aapt2/ResourceTable_test.cpp
index 7fa8ea2..1a1f73f 100644
--- a/tools/aapt2/ResourceTable_test.cpp
+++ b/tools/aapt2/ResourceTable_test.cpp
@@ -24,6 +24,7 @@
#include <ostream>
#include <string>
+using ::android::ConfigDescription;
using ::android::StringPiece;
using ::testing::Eq;
using ::testing::NotNull;
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 560077c..82d9e04 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -31,6 +31,7 @@
#include "util/Util.h"
using ::aapt::text::Utf8Iterator;
+using ::android::ConfigDescription;
using ::android::StringPiece;
using ::android::StringPiece16;
using ::android::base::StringPrintf;
diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h
index 7af2fe0..e2f1c89 100644
--- a/tools/aapt2/ResourceUtils.h
+++ b/tools/aapt2/ResourceUtils.h
@@ -20,6 +20,7 @@
#include <functional>
#include <memory>
+#include "androidfw/ConfigDescription.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/StringPiece.h"
@@ -219,7 +220,8 @@
// Parses the binary form of a resource value. `type` is used as a hint to know when a value is
// an ID versus a False boolean value, etc. `config` is for sorting strings in the string pool.
-std::unique_ptr<Item> ParseBinaryResValue(const ResourceType& type, const ConfigDescription& config,
+std::unique_ptr<Item> ParseBinaryResValue(const ResourceType& type,
+ const android::ConfigDescription& config,
const android::ResStringPool& src_pool,
const android::Res_value& res_value,
StringPool* dst_pool);
diff --git a/tools/aapt2/StringPool.h b/tools/aapt2/StringPool.h
index f5b464d..1006ca9 100644
--- a/tools/aapt2/StringPool.h
+++ b/tools/aapt2/StringPool.h
@@ -24,9 +24,9 @@
#include <vector>
#include "android-base/macros.h"
+#include "androidfw/ConfigDescription.h"
#include "androidfw/StringPiece.h"
-#include "ConfigDescription.h"
#include "Diagnostics.h"
#include "util/BigBuffer.h"
@@ -60,12 +60,12 @@
kLowPriority = 0xffffffffu,
};
uint32_t priority = kNormalPriority;
- ConfigDescription config;
+ android::ConfigDescription config;
Context() = default;
- Context(uint32_t p, const ConfigDescription& c) : priority(p), config(c) {}
+ Context(uint32_t p, const android::ConfigDescription& c) : priority(p), config(c) {}
explicit Context(uint32_t p) : priority(p) {}
- explicit Context(const ConfigDescription& c) : priority(kNormalPriority), config(c) {
+ explicit Context(const android::ConfigDescription& c) : priority(kNormalPriority), config(c) {
}
};
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index ab8a4b7..411ad74 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -21,11 +21,11 @@
#include "android-base/errors.h"
#include "android-base/file.h"
#include "android-base/utf8.h"
+#include "androidfw/ConfigDescription.h"
#include "androidfw/StringPiece.h"
#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
-#include "ConfigDescription.h"
#include "Diagnostics.h"
#include "Flags.h"
#include "ResourceParser.h"
@@ -50,6 +50,7 @@
using ::aapt::io::FileInputStream;
using ::aapt::text::Printer;
+using ::android::ConfigDescription;
using ::android::StringPiece;
using ::android::base::SystemErrorCodeToString;
using ::google::protobuf::io::CopyingOutputStreamAdaptor;
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index db42e7c..60cab5d 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -24,13 +24,13 @@
#include "android-base/errors.h"
#include "android-base/file.h"
#include "android-base/stringprintf.h"
+#include "androidfw/Locale.h"
#include "androidfw/StringPiece.h"
#include "AppInfo.h"
#include "Debug.h"
#include "Flags.h"
#include "LoadedApk.h"
-#include "Locale.h"
#include "NameMangler.h"
#include "ResourceUtils.h"
#include "ResourceValues.h"
@@ -68,6 +68,7 @@
#include "xml/XmlDom.h"
using ::aapt::io::FileInputStream;
+using ::android::ConfigDescription;
using ::android::StringPiece;
using ::android::base::StringPrintf;
@@ -105,6 +106,7 @@
bool no_version_vectors = false;
bool no_version_transitions = false;
bool no_resource_deduping = false;
+ bool no_resource_removal = false;
bool no_xml_namespaces = false;
bool do_not_compress_anything = false;
std::unordered_set<std::string> extensions_to_not_compress;
@@ -1806,10 +1808,12 @@
// Before we process anything, remove the resources whose default values don't exist.
// We want to force any references to these to fail the build.
- if (!NoDefaultResourceRemover{}.Consume(context_, &final_table_)) {
- context_->GetDiagnostics()->Error(DiagMessage()
- << "failed removing resources with no defaults");
- return 1;
+ if (!options_.no_resource_removal) {
+ if (!NoDefaultResourceRemover{}.Consume(context_, &final_table_)) {
+ context_->GetDiagnostics()->Error(DiagMessage()
+ << "failed removing resources with no defaults");
+ return 1;
+ }
}
ReferenceLinker linker;
@@ -2084,6 +2088,10 @@
"Disables automatic deduping of resources with\n"
"identical values across compatible configurations.",
&options.no_resource_deduping)
+ .OptionalSwitch("--no-resource-removal",
+ "Disables automatic removal of resources without defaults. Use this only\n"
+ "when building runtime resource overlay packages.",
+ &options.no_resource_removal)
.OptionalSwitch("--enable-sparse-encoding",
"Enables encoding sparse entries using a binary search tree.\n"
"This decreases APK size at the cost of resource retrieval performance.",
diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp
index 9c76119..45297a7 100644
--- a/tools/aapt2/cmd/Optimize.cpp
+++ b/tools/aapt2/cmd/Optimize.cpp
@@ -20,6 +20,7 @@
#include "android-base/file.h"
#include "android-base/stringprintf.h"
+#include "androidfw/ConfigDescription.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/StringPiece.h"
@@ -45,6 +46,7 @@
using ::aapt::configuration::Abi;
using ::aapt::configuration::OutputArtifact;
+using ::android::ConfigDescription;
using ::android::ResTable_config;
using ::android::StringPiece;
using ::android::base::ReadFileToString;
diff --git a/tools/aapt2/cmd/Util.cpp b/tools/aapt2/cmd/Util.cpp
index 8b3a670..25010c5 100644
--- a/tools/aapt2/cmd/Util.cpp
+++ b/tools/aapt2/cmd/Util.cpp
@@ -19,15 +19,17 @@
#include <vector>
#include "android-base/logging.h"
+#include "androidfw/ConfigDescription.h"
+#include "androidfw/Locale.h"
-#include "ConfigDescription.h"
-#include "Locale.h"
#include "ResourceUtils.h"
#include "ValueVisitor.h"
#include "split/TableSplitter.h"
#include "util/Maybe.h"
#include "util/Util.h"
+using ::android::ConfigDescription;
+using ::android::LocaleValue;
using ::android::StringPiece;
namespace aapt {
diff --git a/tools/aapt2/compile/PseudolocaleGenerator.cpp b/tools/aapt2/compile/PseudolocaleGenerator.cpp
index 36c24bc..c5de9e0 100644
--- a/tools/aapt2/compile/PseudolocaleGenerator.cpp
+++ b/tools/aapt2/compile/PseudolocaleGenerator.cpp
@@ -24,6 +24,7 @@
#include "compile/Pseudolocalizer.h"
#include "util/Util.h"
+using ::android::ConfigDescription;
using ::android::StringPiece;
using ::android::StringPiece16;
diff --git a/tools/aapt2/compile/PseudolocaleGenerator_test.cpp b/tools/aapt2/compile/PseudolocaleGenerator_test.cpp
index 711558a..3135802 100644
--- a/tools/aapt2/compile/PseudolocaleGenerator_test.cpp
+++ b/tools/aapt2/compile/PseudolocaleGenerator_test.cpp
@@ -19,6 +19,8 @@
#include "test/Test.h"
#include "util/Util.h"
+using ::android::ConfigDescription;
+
namespace aapt {
TEST(PseudolocaleGeneratorTest, PseudolocalizeStyledString) {
diff --git a/tools/aapt2/configuration/ConfigurationParser.cpp b/tools/aapt2/configuration/ConfigurationParser.cpp
index 902334b..dd06b38 100644
--- a/tools/aapt2/configuration/ConfigurationParser.cpp
+++ b/tools/aapt2/configuration/ConfigurationParser.cpp
@@ -25,8 +25,8 @@
#include "android-base/file.h"
#include "android-base/logging.h"
+#include "androidfw/ConfigDescription.h"
-#include "ConfigDescription.h"
#include "Diagnostics.h"
#include "ResourceUtils.h"
#include "configuration/ConfigurationParser.internal.h"
@@ -40,6 +40,8 @@
#include "xml/XmlDom.h"
#include "xml/XmlUtil.h"
+using ::android::ConfigDescription;
+
namespace aapt {
namespace {
diff --git a/tools/aapt2/configuration/ConfigurationParser.h b/tools/aapt2/configuration/ConfigurationParser.h
index 7f1d445..b9e3be9 100644
--- a/tools/aapt2/configuration/ConfigurationParser.h
+++ b/tools/aapt2/configuration/ConfigurationParser.h
@@ -22,7 +22,8 @@
#include <unordered_map>
#include <vector>
-#include "ConfigDescription.h"
+#include "androidfw/ConfigDescription.h"
+
#include "Diagnostics.h"
#include "util/Maybe.h"
@@ -109,8 +110,8 @@
std::string name;
int version;
std::vector<Abi> abis;
- std::vector<ConfigDescription> screen_densities;
- std::vector<ConfigDescription> locales;
+ std::vector<android::ConfigDescription> screen_densities;
+ std::vector<android::ConfigDescription> locales;
Maybe<AndroidSdk> android_sdk;
std::vector<DeviceFeature> features;
std::vector<GlTexture> textures;
diff --git a/tools/aapt2/configuration/ConfigurationParser.internal.h b/tools/aapt2/configuration/ConfigurationParser.internal.h
index f071a69..c541688 100644
--- a/tools/aapt2/configuration/ConfigurationParser.internal.h
+++ b/tools/aapt2/configuration/ConfigurationParser.internal.h
@@ -17,6 +17,8 @@
#ifndef AAPT2_CONFIGURATIONPARSER_INTERNAL_H
#define AAPT2_CONFIGURATIONPARSER_INTERNAL_H
+#include "androidfw/ConfigDescription.h"
+
#include "configuration/ConfigurationParser.h"
#include <algorithm>
@@ -148,8 +150,8 @@
Maybe<std::string> artifact_format;
Group<Abi> abi_groups;
- Group<ConfigDescription> screen_density_groups;
- Group<ConfigDescription> locale_groups;
+ Group<android::ConfigDescription> screen_density_groups;
+ Group<android::ConfigDescription> locale_groups;
Group<DeviceFeature> device_feature_groups;
Group<GlTexture> gl_texture_groups;
Entry<AndroidSdk> android_sdks;
diff --git a/tools/aapt2/configuration/ConfigurationParser_test.cpp b/tools/aapt2/configuration/ConfigurationParser_test.cpp
index febbb2e..960880a 100644
--- a/tools/aapt2/configuration/ConfigurationParser_test.cpp
+++ b/tools/aapt2/configuration/ConfigurationParser_test.cpp
@@ -26,6 +26,8 @@
#include "test/Test.h"
#include "xml/XmlDom.h"
+using ::android::ConfigDescription;
+
namespace aapt {
namespace configuration {
diff --git a/tools/aapt2/filter/ConfigFilter.cpp b/tools/aapt2/filter/ConfigFilter.cpp
index 5fbe77e..9d10d59 100644
--- a/tools/aapt2/filter/ConfigFilter.cpp
+++ b/tools/aapt2/filter/ConfigFilter.cpp
@@ -16,9 +16,10 @@
#include "filter/ConfigFilter.h"
+#include "androidfw/ConfigDescription.h"
#include "androidfw/ResourceTypes.h"
-#include "ConfigDescription.h"
+using ::android::ConfigDescription;
namespace aapt {
diff --git a/tools/aapt2/filter/ConfigFilter.h b/tools/aapt2/filter/ConfigFilter.h
index ebb8151..c4b7e43 100644
--- a/tools/aapt2/filter/ConfigFilter.h
+++ b/tools/aapt2/filter/ConfigFilter.h
@@ -20,7 +20,7 @@
#include <set>
#include <utility>
-#include "ConfigDescription.h"
+#include "androidfw/ConfigDescription.h"
namespace aapt {
@@ -34,7 +34,7 @@
/**
* Returns true if the filter matches the configuration, false otherwise.
*/
- virtual bool Match(const ConfigDescription& config) const = 0;
+ virtual bool Match(const android::ConfigDescription& config) const = 0;
};
/**
@@ -46,12 +46,12 @@
*/
class AxisConfigFilter : public IConfigFilter {
public:
- void AddConfig(ConfigDescription config);
+ void AddConfig(android::ConfigDescription config);
- bool Match(const ConfigDescription& config) const override;
+ bool Match(const android::ConfigDescription& config) const override;
private:
- std::set<std::pair<ConfigDescription, uint32_t>> configs_;
+ std::set<std::pair<android::ConfigDescription, uint32_t>> configs_;
uint32_t config_mask_ = 0;
};
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.h b/tools/aapt2/format/binary/BinaryResourceParser.h
index a1f9f83..2bdc051 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.h
+++ b/tools/aapt2/format/binary/BinaryResourceParser.h
@@ -20,6 +20,7 @@
#include <string>
#include "android-base/macros.h"
+#include "androidfw/ConfigDescription.h"
#include "androidfw/ResourceTypes.h"
#include "ResourceTable.h"
@@ -54,22 +55,28 @@
bool ParseType(const ResourceTablePackage* package, const android::ResChunk_header* chunk);
bool ParseLibrary(const android::ResChunk_header* chunk);
- std::unique_ptr<Item> ParseValue(const ResourceNameRef& name, const ConfigDescription& config,
+ std::unique_ptr<Item> ParseValue(const ResourceNameRef& name,
+ const android::ConfigDescription& config,
const android::Res_value& value);
- std::unique_ptr<Value> ParseMapEntry(const ResourceNameRef& name, const ConfigDescription& config,
+ std::unique_ptr<Value> ParseMapEntry(const ResourceNameRef& name,
+ const android::ConfigDescription& config,
const android::ResTable_map_entry* map);
- std::unique_ptr<Style> ParseStyle(const ResourceNameRef& name, const ConfigDescription& config,
+ std::unique_ptr<Style> ParseStyle(const ResourceNameRef& name,
+ const android::ConfigDescription& config,
const android::ResTable_map_entry* map);
- std::unique_ptr<Attribute> ParseAttr(const ResourceNameRef& name, const ConfigDescription& config,
+ std::unique_ptr<Attribute> ParseAttr(const ResourceNameRef& name,
+ const android::ConfigDescription& config,
const android::ResTable_map_entry* map);
- std::unique_ptr<Array> ParseArray(const ResourceNameRef& name, const ConfigDescription& config,
+ std::unique_ptr<Array> ParseArray(const ResourceNameRef& name,
+ const android::ConfigDescription& config,
const android::ResTable_map_entry* map);
- std::unique_ptr<Plural> ParsePlural(const ResourceNameRef& name, const ConfigDescription& config,
+ std::unique_ptr<Plural> ParsePlural(const ResourceNameRef& name,
+ const android::ConfigDescription& config,
const android::ResTable_map_entry* map);
/**
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp
index 3b101b7..d1b2fdb 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -19,13 +19,15 @@
#include "android-base/logging.h"
#include "android-base/macros.h"
#include "androidfw/ResourceTypes.h"
+#include "androidfw/Locale.h"
-#include "Locale.h"
#include "ResourceTable.h"
#include "ResourceUtils.h"
#include "ResourceValues.h"
#include "ValueVisitor.h"
+using ::android::ConfigDescription;
+using ::android::LocaleValue;
using ::android::ResStringPool;
namespace aapt {
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.h b/tools/aapt2/format/proto/ProtoDeserialize.h
index 0c581a1..723a1c0 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.h
+++ b/tools/aapt2/format/proto/ProtoDeserialize.h
@@ -18,9 +18,9 @@
#define AAPT_FORMAT_PROTO_PROTODESERIALIZE_H
#include "android-base/macros.h"
+#include "androidfw/ConfigDescription.h"
#include "androidfw/ResourceTypes.h"
-#include "ConfigDescription.h"
#include "Configuration.pb.h"
#include "ResourceTable.h"
#include "ResourceValues.h"
@@ -34,14 +34,15 @@
std::unique_ptr<Value> DeserializeValueFromPb(const pb::Value& pb_value,
const android::ResStringPool& src_pool,
- const ConfigDescription& config,
+ const android::ConfigDescription& config,
StringPool* value_pool, io::IFileCollection* files,
std::string* out_error);
std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item,
const android::ResStringPool& src_pool,
- const ConfigDescription& config, StringPool* value_pool,
- io::IFileCollection* files, std::string* out_error);
+ const android::ConfigDescription& config,
+ StringPool* value_pool, io::IFileCollection* files,
+ std::string* out_error);
std::unique_ptr<xml::XmlResource> DeserializeXmlResourceFromPb(const pb::XmlNode& pb_node,
std::string* out_error);
@@ -49,8 +50,8 @@
bool DeserializeXmlFromPb(const pb::XmlNode& pb_node, xml::Element* out_el, StringPool* value_pool,
std::string* out_error);
-bool DeserializeConfigFromPb(const pb::Configuration& pb_config, ConfigDescription* out_config,
- std::string* out_error);
+bool DeserializeConfigFromPb(const pb::Configuration& pb_config,
+ android::ConfigDescription* out_config, std::string* out_error);
// Optional io::IFileCollection used to lookup references to files in the ResourceTable.
bool DeserializeTableFromPb(const pb::ResourceTable& pb_table, io::IFileCollection* files,
diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp
index 411cc29..7e35ea7 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -19,6 +19,8 @@
#include "ValueVisitor.h"
#include "util/BigBuffer.h"
+using android::ConfigDescription;
+
namespace aapt {
void SerializeStringPoolToPb(const StringPool& pool, pb::StringPool* out_pb_pool, IDiagnostics* diag) {
diff --git a/tools/aapt2/format/proto/ProtoSerialize.h b/tools/aapt2/format/proto/ProtoSerialize.h
index 951494c..c40e5dd 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.h
+++ b/tools/aapt2/format/proto/ProtoSerialize.h
@@ -18,8 +18,8 @@
#define AAPT_FORMAT_PROTO_PROTOSERIALIZE_H
#include "android-base/macros.h"
+#include "androidfw/ConfigDescription.h"
-#include "ConfigDescription.h"
#include "Configuration.pb.h"
#include "ResourceTable.h"
#include "ResourceValues.h"
@@ -49,7 +49,7 @@
void SerializeStringPoolToPb(const StringPool& pool, pb::StringPool* out_pb_pool, IDiagnostics* diag);
// Serializes a ConfigDescription into its protobuf representation.
-void SerializeConfig(const ConfigDescription& config, pb::Configuration* out_pb_config);
+void SerializeConfig(const android::ConfigDescription& config, pb::Configuration* out_pb_config);
// Serializes a ResourceTable into its protobuf representation.
void SerializeTableToPb(const ResourceTable& table, pb::ResourceTable* out_table, IDiagnostics* diag);
diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
index 21fdbd8..a0d92f7 100644
--- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
@@ -20,6 +20,7 @@
#include "format/proto/ProtoDeserialize.h"
#include "test/Test.h"
+using ::android::ConfigDescription;
using ::android::StringPiece;
using ::testing::Eq;
using ::testing::IsEmpty;
diff --git a/tools/aapt2/io/FileStream_test.cpp b/tools/aapt2/io/FileStream_test.cpp
index c0eaa8e..7872738 100644
--- a/tools/aapt2/io/FileStream_test.cpp
+++ b/tools/aapt2/io/FileStream_test.cpp
@@ -41,46 +41,46 @@
ASSERT_FALSE(in.HadError());
EXPECT_THAT(in.ByteCount(), Eq(0u));
- const char* buffer;
+ const void* buffer;
size_t size;
- ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size)) << in.GetError();
+ ASSERT_TRUE(in.Next(&buffer, &size)) << in.GetError();
ASSERT_THAT(size, Eq(10u));
ASSERT_THAT(buffer, NotNull());
EXPECT_THAT(in.ByteCount(), Eq(10u));
- EXPECT_THAT(StringPiece(buffer, size), Eq("this is a "));
+ EXPECT_THAT(StringPiece(reinterpret_cast<const char*>(buffer), size), Eq("this is a "));
- ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+ ASSERT_TRUE(in.Next(&buffer, &size));
ASSERT_THAT(size, Eq(10u));
ASSERT_THAT(buffer, NotNull());
EXPECT_THAT(in.ByteCount(), Eq(20u));
- EXPECT_THAT(StringPiece(buffer, size), Eq("cool strin"));
+ EXPECT_THAT(StringPiece(reinterpret_cast<const char*>(buffer), size), Eq("cool strin"));
in.BackUp(5u);
EXPECT_THAT(in.ByteCount(), Eq(15u));
- ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+ ASSERT_TRUE(in.Next(&buffer, &size));
ASSERT_THAT(size, Eq(5u));
ASSERT_THAT(buffer, NotNull());
ASSERT_THAT(in.ByteCount(), Eq(20u));
- EXPECT_THAT(StringPiece(buffer, size), Eq("strin"));
+ EXPECT_THAT(StringPiece(reinterpret_cast<const char*>(buffer), size), Eq("strin"));
// Backup 1 more than possible. Should clamp.
in.BackUp(11u);
EXPECT_THAT(in.ByteCount(), Eq(10u));
- ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+ ASSERT_TRUE(in.Next(&buffer, &size));
ASSERT_THAT(size, Eq(10u));
ASSERT_THAT(buffer, NotNull());
ASSERT_THAT(in.ByteCount(), Eq(20u));
- EXPECT_THAT(StringPiece(buffer, size), Eq("cool strin"));
+ EXPECT_THAT(StringPiece(reinterpret_cast<const char*>(buffer), size), Eq("cool strin"));
- ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+ ASSERT_TRUE(in.Next(&buffer, &size));
ASSERT_THAT(size, Eq(1u));
ASSERT_THAT(buffer, NotNull());
ASSERT_THAT(in.ByteCount(), Eq(21u));
- EXPECT_THAT(StringPiece(buffer, size), Eq("g"));
+ EXPECT_THAT(StringPiece(reinterpret_cast<const char*>(buffer), size), Eq("g"));
- EXPECT_FALSE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+ EXPECT_FALSE(in.Next(&buffer, &size));
EXPECT_FALSE(in.HadError());
}
@@ -93,25 +93,25 @@
ASSERT_FALSE(out.HadError());
EXPECT_THAT(out.ByteCount(), Eq(0u));
- char* buffer;
+ void* buffer;
size_t size;
- ASSERT_TRUE(out.Next(reinterpret_cast<void**>(&buffer), &size));
+ ASSERT_TRUE(out.Next(&buffer, &size));
ASSERT_THAT(size, Eq(10u));
ASSERT_THAT(buffer, NotNull());
EXPECT_THAT(out.ByteCount(), Eq(10u));
- memcpy(buffer, input.c_str(), size);
+ memcpy(reinterpret_cast<char*>(buffer), input.c_str(), size);
- ASSERT_TRUE(out.Next(reinterpret_cast<void**>(&buffer), &size));
+ ASSERT_TRUE(out.Next(&buffer, &size));
ASSERT_THAT(size, Eq(10u));
ASSERT_THAT(buffer, NotNull());
EXPECT_THAT(out.ByteCount(), Eq(20u));
- memcpy(buffer, input.c_str() + 10u, size);
+ memcpy(reinterpret_cast<char*>(buffer), input.c_str() + 10u, size);
- ASSERT_TRUE(out.Next(reinterpret_cast<void**>(&buffer), &size));
+ ASSERT_TRUE(out.Next(&buffer, &size));
ASSERT_THAT(size, Eq(10u));
ASSERT_THAT(buffer, NotNull());
EXPECT_THAT(out.ByteCount(), Eq(30u));
- buffer[0] = input[20u];
+ reinterpret_cast<char*>(buffer)[0] = input[20u];
out.BackUp(size - 1);
EXPECT_THAT(out.ByteCount(), Eq(21u));
diff --git a/tools/aapt2/java/ManifestClassGenerator.cpp b/tools/aapt2/java/ManifestClassGenerator.cpp
index be67c9c..10e504e 100644
--- a/tools/aapt2/java/ManifestClassGenerator.cpp
+++ b/tools/aapt2/java/ManifestClassGenerator.cpp
@@ -26,21 +26,20 @@
#include "util/Maybe.h"
#include "xml/XmlDom.h"
-using ::android::StringPiece;
using ::aapt::text::IsJavaIdentifier;
namespace aapt {
-static Maybe<StringPiece> ExtractJavaIdentifier(IDiagnostics* diag, const Source& source,
+static Maybe<std::string> ExtractJavaIdentifier(IDiagnostics* diag, const Source& source,
const std::string& value) {
- StringPiece result = value;
+ std::string result = value;
size_t pos = value.rfind('.');
if (pos != std::string::npos) {
result = result.substr(pos + 1);
}
// Normalize only the java identifier, leave the original value unchanged.
- if (result.contains("-")) {
+ if (result.find("-") != std::string::npos) {
result = JavaClassGenerator::TransformToFieldName(result);
}
@@ -64,7 +63,7 @@
return false;
}
- Maybe<StringPiece> result =
+ Maybe<std::string> result =
ExtractJavaIdentifier(diag, source.WithLine(el->line_number), attr->value);
if (!result) {
return false;
diff --git a/tools/aapt2/java/ProguardRules_test.cpp b/tools/aapt2/java/ProguardRules_test.cpp
index 37d1a5f..f774e3a 100644
--- a/tools/aapt2/java/ProguardRules_test.cpp
+++ b/tools/aapt2/java/ProguardRules_test.cpp
@@ -21,6 +21,7 @@
#include "test/Test.h"
using ::aapt::io::StringOutputStream;
+using ::android::ConfigDescription;
using ::testing::HasSubstr;
using ::testing::Not;
diff --git a/tools/aapt2/link/AutoVersioner.cpp b/tools/aapt2/link/AutoVersioner.cpp
index f80c6e9..960c7d4 100644
--- a/tools/aapt2/link/AutoVersioner.cpp
+++ b/tools/aapt2/link/AutoVersioner.cpp
@@ -20,14 +20,16 @@
#include "android-base/logging.h"
-#include "ConfigDescription.h"
#include "ResourceTable.h"
#include "SdkConstants.h"
#include "ValueVisitor.h"
+using android::ConfigDescription;
+
namespace aapt {
-bool ShouldGenerateVersionedResource(const ResourceEntry* entry, const ConfigDescription& config,
+bool ShouldGenerateVersionedResource(const ResourceEntry* entry,
+ const ConfigDescription& config,
const ApiVersion sdk_version_to_generate) {
// We assume the caller is trying to generate a version greater than the current configuration.
CHECK(sdk_version_to_generate > config.sdkVersion);
diff --git a/tools/aapt2/link/AutoVersioner_test.cpp b/tools/aapt2/link/AutoVersioner_test.cpp
index 49639f8..1117472 100644
--- a/tools/aapt2/link/AutoVersioner_test.cpp
+++ b/tools/aapt2/link/AutoVersioner_test.cpp
@@ -16,9 +16,11 @@
#include "link/Linkers.h"
-#include "ConfigDescription.h"
+#include "androidfw/ConfigDescription.h"
+
#include "test/Test.h"
+using ::android::ConfigDescription;
using ::testing::NotNull;
namespace aapt {
diff --git a/tools/aapt2/link/Linkers.h b/tools/aapt2/link/Linkers.h
index 3c9c476..c9b8d39 100644
--- a/tools/aapt2/link/Linkers.h
+++ b/tools/aapt2/link/Linkers.h
@@ -21,6 +21,7 @@
#include <unordered_set>
#include "android-base/macros.h"
+#include "androidfw/ConfigDescription.h"
#include "androidfw/StringPiece.h"
#include "Resource.h"
@@ -32,7 +33,6 @@
class ResourceTable;
class ResourceEntry;
-struct ConfigDescription;
// Defines the context in which a resource value is defined. Most resources are defined with the
// implicit package name of their compilation context. Understanding the package name of a resource
@@ -43,12 +43,14 @@
// Determines whether a versioned resource should be created. If a versioned resource already
// exists, it takes precedence.
-bool ShouldGenerateVersionedResource(const ResourceEntry* entry, const ConfigDescription& config,
+bool ShouldGenerateVersionedResource(const ResourceEntry* entry,
+ const android::ConfigDescription& config,
const ApiVersion sdk_version_to_generate);
// Finds the next largest ApiVersion of the config which is identical to the given config except
// for sdkVersion.
-ApiVersion FindNextApiVersionForConfig(const ResourceEntry* entry, const ConfigDescription& config);
+ApiVersion FindNextApiVersionForConfig(const ResourceEntry* entry,
+ const android::ConfigDescription& config);
class AutoVersioner : public IResourceTableConsumer {
public:
diff --git a/tools/aapt2/link/NoDefaultResourceRemover.cpp b/tools/aapt2/link/NoDefaultResourceRemover.cpp
index cfb4b26..13054bf 100644
--- a/tools/aapt2/link/NoDefaultResourceRemover.cpp
+++ b/tools/aapt2/link/NoDefaultResourceRemover.cpp
@@ -14,12 +14,16 @@
* limitations under the License.
*/
+#include "androidfw/Locale.h"
+
#include "link/NoDefaultResourceRemover.h"
#include <algorithm>
#include "ResourceTable.h"
+using android::ConfigDescription;
+
namespace aapt {
static bool IsDefaultConfigRequired(const ConfigDescription& config) {
diff --git a/tools/aapt2/link/ProductFilter_test.cpp b/tools/aapt2/link/ProductFilter_test.cpp
index 86dd56a..dd47674 100644
--- a/tools/aapt2/link/ProductFilter_test.cpp
+++ b/tools/aapt2/link/ProductFilter_test.cpp
@@ -18,6 +18,8 @@
#include "test/Test.h"
+using ::android::ConfigDescription;
+
namespace aapt {
TEST(ProductFilterTest, SelectTwoProducts) {
diff --git a/tools/aapt2/optimize/MultiApkGenerator.cpp b/tools/aapt2/optimize/MultiApkGenerator.cpp
index 588b331..aa9f9ab 100644
--- a/tools/aapt2/optimize/MultiApkGenerator.cpp
+++ b/tools/aapt2/optimize/MultiApkGenerator.cpp
@@ -20,6 +20,7 @@
#include <regex>
#include <string>
+#include "androidfw/ConfigDescription.h"
#include "androidfw/StringPiece.h"
#include "LoadedApk.h"
@@ -43,6 +44,7 @@
using ::aapt::configuration::OutputArtifact;
using ::aapt::xml::kSchemaAndroid;
using ::aapt::xml::XmlResource;
+using ::android::ConfigDescription;
using ::android::StringPiece;
/**
diff --git a/tools/aapt2/optimize/MultiApkGenerator.h b/tools/aapt2/optimize/MultiApkGenerator.h
index c858879..4a5a6c3d 100644
--- a/tools/aapt2/optimize/MultiApkGenerator.h
+++ b/tools/aapt2/optimize/MultiApkGenerator.h
@@ -22,6 +22,8 @@
#include <unordered_set>
#include <vector>
+#include "androidfw/ConfigDescription.h"
+
#include "Diagnostics.h"
#include "LoadedApk.h"
#include "configuration/ConfigurationParser.h"
@@ -66,7 +68,7 @@
/**
* Adds the <screen> elements to the parent node for the provided density configuration.
*/
- void AddScreens(const ConfigDescription& config, xml::Element* parent);
+ void AddScreens(const android::ConfigDescription& config, xml::Element* parent);
LoadedApk* apk_;
IAaptContext* context_;
diff --git a/tools/aapt2/optimize/MultiApkGenerator_test.cpp b/tools/aapt2/optimize/MultiApkGenerator_test.cpp
index 80eb737..7d87eb8 100644
--- a/tools/aapt2/optimize/MultiApkGenerator_test.cpp
+++ b/tools/aapt2/optimize/MultiApkGenerator_test.cpp
@@ -31,6 +31,8 @@
#include "test/Context.h"
#include "test/Test.h"
+using ::android::ConfigDescription;
+
namespace aapt {
namespace {
diff --git a/tools/aapt2/optimize/ResourceDeduper.cpp b/tools/aapt2/optimize/ResourceDeduper.cpp
index 9d16268..ee2dfbc 100644
--- a/tools/aapt2/optimize/ResourceDeduper.cpp
+++ b/tools/aapt2/optimize/ResourceDeduper.cpp
@@ -21,6 +21,8 @@
#include "DominatorTree.h"
#include "ResourceTable.h"
+using android::ConfigDescription;
+
namespace aapt {
namespace {
diff --git a/tools/aapt2/optimize/ResourceDeduper_test.cpp b/tools/aapt2/optimize/ResourceDeduper_test.cpp
index d9f384c0..2e098ae 100644
--- a/tools/aapt2/optimize/ResourceDeduper_test.cpp
+++ b/tools/aapt2/optimize/ResourceDeduper_test.cpp
@@ -20,6 +20,7 @@
#include "test/Test.h"
using ::aapt::test::HasValue;
+using ::android::ConfigDescription;
using ::testing::Not;
namespace aapt {
diff --git a/tools/aapt2/optimize/VersionCollapser.cpp b/tools/aapt2/optimize/VersionCollapser.cpp
index cc1fc1e..f985604 100644
--- a/tools/aapt2/optimize/VersionCollapser.cpp
+++ b/tools/aapt2/optimize/VersionCollapser.cpp
@@ -21,6 +21,8 @@
#include "ResourceTable.h"
+using android::ConfigDescription;
+
namespace aapt {
template <typename Iterator, typename Pred>
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index 70efbf5..a844a43 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -21,15 +21,16 @@
#include "android-base/logging.h"
#include "android-base/stringprintf.h"
#include "androidfw/AssetManager.h"
+#include "androidfw/ConfigDescription.h"
#include "androidfw/ResourceTypes.h"
-#include "ConfigDescription.h"
#include "NameMangler.h"
#include "Resource.h"
#include "ResourceUtils.h"
#include "ValueVisitor.h"
#include "util/Util.h"
+using ::android::ConfigDescription;
using ::android::StringPiece;
using ::android::StringPiece16;
diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp
index e991743..1dd5502 100644
--- a/tools/aapt2/split/TableSplitter.cpp
+++ b/tools/aapt2/split/TableSplitter.cpp
@@ -24,11 +24,13 @@
#include <vector>
#include "android-base/logging.h"
+#include "androidfw/ConfigDescription.h"
-#include "ConfigDescription.h"
#include "ResourceTable.h"
#include "util/Util.h"
+using ::android::ConfigDescription;
+
namespace aapt {
using ConfigClaimedMap = std::unordered_map<ResourceConfigValue*, bool>;
diff --git a/tools/aapt2/split/TableSplitter.h b/tools/aapt2/split/TableSplitter.h
index 6aec257..91afaa3 100644
--- a/tools/aapt2/split/TableSplitter.h
+++ b/tools/aapt2/split/TableSplitter.h
@@ -20,8 +20,8 @@
#include <set>
#include <vector>
#include "android-base/macros.h"
+#include "androidfw/ConfigDescription.h"
-#include "ConfigDescription.h"
#include "ResourceTable.h"
#include "filter/ConfigFilter.h"
#include "process/IResourceTableConsumer.h"
@@ -29,7 +29,7 @@
namespace aapt {
struct SplitConstraints {
- std::set<ConfigDescription> configs;
+ std::set<android::ConfigDescription> configs;
};
struct TableSplitterOptions {
diff --git a/tools/aapt2/split/TableSplitter_test.cpp b/tools/aapt2/split/TableSplitter_test.cpp
index d52f4b44..cdf0738 100644
--- a/tools/aapt2/split/TableSplitter_test.cpp
+++ b/tools/aapt2/split/TableSplitter_test.cpp
@@ -18,6 +18,8 @@
#include "test/Test.h"
+using ::android::ConfigDescription;
+
namespace aapt {
TEST(TableSplitterTest, NoSplitPreferredDensity) {
diff --git a/tools/aapt2/test/Builders.cpp b/tools/aapt2/test/Builders.cpp
index c4eab12..f33ae31 100644
--- a/tools/aapt2/test/Builders.cpp
+++ b/tools/aapt2/test/Builders.cpp
@@ -28,6 +28,7 @@
using ::aapt::configuration::ConfiguredArtifact;
using ::aapt::configuration::GetOrCreateGroup;
using ::aapt::io::StringInputStream;
+using ::android::ConfigDescription;
using ::android::StringPiece;
namespace aapt {
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index fd5262a..a88b11e 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -20,6 +20,7 @@
#include <memory>
#include "android-base/macros.h"
+#include "androidfw/ConfigDescription.h"
#include "Resource.h"
#include "ResourceTable.h"
@@ -40,7 +41,8 @@
ResourceTableBuilder& SetPackageId(const android::StringPiece& package_name, uint8_t id);
ResourceTableBuilder& AddSimple(const android::StringPiece& name, const ResourceId& id = {});
- ResourceTableBuilder& AddSimple(const android::StringPiece& name, const ConfigDescription& config,
+ ResourceTableBuilder& AddSimple(const android::StringPiece& name,
+ const android::ConfigDescription& config,
const ResourceId& id = {});
ResourceTableBuilder& AddReference(const android::StringPiece& name,
const android::StringPiece& ref);
@@ -51,7 +53,8 @@
ResourceTableBuilder& AddString(const android::StringPiece& name, const ResourceId& id,
const android::StringPiece& str);
ResourceTableBuilder& AddString(const android::StringPiece& name, const ResourceId& id,
- const ConfigDescription& config, const android::StringPiece& str);
+ const android::ConfigDescription& config,
+ const android::StringPiece& str);
ResourceTableBuilder& AddFileReference(const android::StringPiece& name,
const android::StringPiece& path,
io::IFile* file = nullptr);
@@ -60,12 +63,13 @@
io::IFile* file = nullptr);
ResourceTableBuilder& AddFileReference(const android::StringPiece& name,
const android::StringPiece& path,
- const ConfigDescription& config,
+ const android::ConfigDescription& config,
io::IFile* file = nullptr);
ResourceTableBuilder& AddValue(const android::StringPiece& name, std::unique_ptr<Value> value);
ResourceTableBuilder& AddValue(const android::StringPiece& name, const ResourceId& id,
std::unique_ptr<Value> value);
- ResourceTableBuilder& AddValue(const android::StringPiece& name, const ConfigDescription& config,
+ ResourceTableBuilder& AddValue(const android::StringPiece& name,
+ const android::ConfigDescription& config,
const ResourceId& id, std::unique_ptr<Value> value);
ResourceTableBuilder& SetSymbolState(const android::StringPiece& name, const ResourceId& id,
Visibility::Level level, bool allow_new = false);
@@ -163,8 +167,8 @@
ArtifactBuilder& SetName(const std::string& name);
ArtifactBuilder& SetVersion(int version);
ArtifactBuilder& AddAbi(configuration::Abi abi);
- ArtifactBuilder& AddDensity(const ConfigDescription& density);
- ArtifactBuilder& AddLocale(const ConfigDescription& locale);
+ ArtifactBuilder& AddDensity(const android::ConfigDescription& density);
+ ArtifactBuilder& AddLocale(const android::ConfigDescription& locale);
ArtifactBuilder& SetAndroidSdk(int min_sdk);
configuration::OutputArtifact Build();
diff --git a/tools/aapt2/test/Common.cpp b/tools/aapt2/test/Common.cpp
index 0fabbc4..b54c155 100644
--- a/tools/aapt2/test/Common.cpp
+++ b/tools/aapt2/test/Common.cpp
@@ -16,6 +16,8 @@
#include "test/Common.h"
+using android::ConfigDescription;
+
namespace aapt {
namespace test {
diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h
index aca161a..50b41f1 100644
--- a/tools/aapt2/test/Common.h
+++ b/tools/aapt2/test/Common.h
@@ -21,11 +21,11 @@
#include "android-base/logging.h"
#include "android-base/macros.h"
+#include "androidfw/ConfigDescription.h"
#include "androidfw/StringPiece.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "ConfigDescription.h"
#include "Debug.h"
#include "ResourceTable.h"
#include "ResourceUtils.h"
@@ -45,15 +45,15 @@
return ref.ToResourceName();
}
-inline ConfigDescription ParseConfigOrDie(const android::StringPiece& str) {
- ConfigDescription config;
- CHECK(ConfigDescription::Parse(str, &config)) << "invalid configuration: " << str;
+inline android::ConfigDescription ParseConfigOrDie(const android::StringPiece& str) {
+ android::ConfigDescription config;
+ CHECK(android::ConfigDescription::Parse(str, &config)) << "invalid configuration: " << str;
return config;
}
template <typename T = Value>
T* GetValueForConfigAndProduct(ResourceTable* table, const android::StringPiece& res_name,
- const ConfigDescription& config,
+ const android::ConfigDescription& config,
const android::StringPiece& product) {
Maybe<ResourceTable::SearchResult> result = table->FindResource(ParseNameOrDie(res_name));
if (result) {
@@ -68,12 +68,12 @@
template <>
Value* GetValueForConfigAndProduct<Value>(ResourceTable* table,
const android::StringPiece& res_name,
- const ConfigDescription& config,
+ const android::ConfigDescription& config,
const android::StringPiece& product);
template <typename T = Value>
T* GetValueForConfig(ResourceTable* table, const android::StringPiece& res_name,
- const ConfigDescription& config) {
+ const android::ConfigDescription& config) {
return GetValueForConfigAndProduct<T>(table, res_name, config, {});
}
diff --git a/tools/aapt2/util/BigBuffer.h b/tools/aapt2/util/BigBuffer.h
index 3045255..d4b3abc 100644
--- a/tools/aapt2/util/BigBuffer.h
+++ b/tools/aapt2/util/BigBuffer.h
@@ -68,7 +68,7 @@
*/
explicit BigBuffer(size_t block_size);
- BigBuffer(BigBuffer&& rhs);
+ BigBuffer(BigBuffer&& rhs) noexcept;
/**
* Number of occupied bytes in all the allocated blocks.
@@ -136,7 +136,7 @@
inline BigBuffer::BigBuffer(size_t block_size)
: block_size_(block_size), size_(0) {}
-inline BigBuffer::BigBuffer(BigBuffer&& rhs)
+inline BigBuffer::BigBuffer(BigBuffer&& rhs) noexcept
: block_size_(rhs.block_size_),
size_(rhs.size_),
blocks_(std::move(rhs.blocks_)) {}
diff --git a/tools/aapt2/util/ImmutableMap.h b/tools/aapt2/util/ImmutableMap.h
index 59858e4..1727b18 100644
--- a/tools/aapt2/util/ImmutableMap.h
+++ b/tools/aapt2/util/ImmutableMap.h
@@ -32,8 +32,8 @@
using const_iterator =
typename std::vector<std::pair<TKey, TValue>>::const_iterator;
- ImmutableMap(ImmutableMap&&) = default;
- ImmutableMap& operator=(ImmutableMap&&) = default;
+ ImmutableMap(ImmutableMap&&) noexcept = default;
+ ImmutableMap& operator=(ImmutableMap&&) noexcept = default;
static ImmutableMap<TKey, TValue> CreatePreSorted(
std::initializer_list<std::pair<TKey, TValue>> list) {
diff --git a/tools/aapt2/util/Maybe.h b/tools/aapt2/util/Maybe.h
index 9a82418..031276c 100644
--- a/tools/aapt2/util/Maybe.h
+++ b/tools/aapt2/util/Maybe.h
@@ -46,7 +46,7 @@
template <typename U>
Maybe(const Maybe<U>& rhs); // NOLINT(implicit)
- Maybe(Maybe&& rhs);
+ Maybe(Maybe&& rhs) noexcept;
template <typename U>
Maybe(Maybe<U>&& rhs); // NOLINT(implicit)
@@ -56,7 +56,7 @@
template <typename U>
Maybe& operator=(const Maybe<U>& rhs);
- Maybe& operator=(Maybe&& rhs);
+ Maybe& operator=(Maybe&& rhs) noexcept;
template <typename U>
Maybe& operator=(Maybe<U>&& rhs);
@@ -134,7 +134,7 @@
}
template <typename T>
-Maybe<T>::Maybe(Maybe&& rhs) : nothing_(rhs.nothing_) {
+Maybe<T>::Maybe(Maybe&& rhs) noexcept : nothing_(rhs.nothing_) {
if (!rhs.nothing_) {
rhs.nothing_ = true;
@@ -192,7 +192,7 @@
}
template <typename T>
-inline Maybe<T>& Maybe<T>::operator=(Maybe&& rhs) {
+inline Maybe<T>& Maybe<T>::operator=(Maybe&& rhs) noexcept {
// Delegate to the actual assignment.
return move(std::forward<Maybe<T>>(rhs));
}
diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py
index 6c46e67..fdc800b 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists.py
@@ -212,8 +212,8 @@
move_from_files(args.input_greylists, uncategorized, light_greylist)
move_from_files(args.input_blacklists, uncategorized, blacklist)
- # Iterate over all uncategorized members and move serialization API to light greylist.
- move_serialization(uncategorized, light_greylist)
+ # Iterate over all uncategorized members and move serialization API to whitelist.
+ move_serialization(uncategorized, whitelist)
# Extract package names of members from whitelist and light greylist, which
# are assumed to have been finalized at this point. Assign all uncategorized
diff --git a/tools/hiddenapi/generate_hiddenapi_lists_test.py b/tools/hiddenapi/generate_hiddenapi_lists_test.py
index 8f79318..4716241 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists_test.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists_test.py
@@ -85,5 +85,23 @@
self.assertEqual(
dst, set([ "Lfoo/bar/ClassA;->abc()J", "Lfoo/bar/ClassA;->def()J" ]))
+ def test_move_serialization(self):
+ # All the entries should be moved apart from the last one
+ src = set([ "Lfoo/bar/ClassA;->readObject(Ljava/io/ObjectInputStream;)V",
+ "Lfoo/bar/ClassA;->readObjectNoData()V",
+ "Lfoo/bar/ClassA;->readResolve()Ljava/lang/Object;",
+ "Lfoo/bar/ClassA;->serialVersionUID:J",
+ "Lfoo/bar/ClassA;->serialPersistentFields:[Ljava/io/ObjectStreamField;",
+ "Lfoo/bar/ClassA;->writeObject(Ljava/io/ObjectOutputStream;)V",
+ "Lfoo/bar/ClassA;->writeReplace()Ljava/lang/Object;",
+ # Should not be moved as signature does not match
+ "Lfoo/bar/ClassA;->readObject(Ljava/io/ObjectInputStream;)I"])
+ expectedToMove = len(src) - 1
+ dst = set()
+ packages = set([ "Lfoo/bar/" ])
+ move_serialization(src, dst)
+ self.assertEqual(len(src), 1)
+ self.assertEqual(len(dst), expectedToMove)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index 3689a8f..4b5677a 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -140,7 +140,7 @@
size_t base = 0;
size_t found;
while (true) {
- found = args.find_first_of(" ", base);
+ found = args.find_first_of(' ', base);
if (found != base) {
string arg = args.substr(base, found - base);
printf(" \"%s\",", arg.c_str());