Merge "public API for VideoProfile.CameraCapability with zoom"
diff --git a/Android.bp b/Android.bp
index 7818d3d..2b64932 100644
--- a/Android.bp
+++ b/Android.bp
@@ -502,6 +502,7 @@
"telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl",
"telephony/java/android/telephony/ims/aidl/IImsServiceControllerListener.aidl",
"telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl",
+ "telephony/java/android/telephony/ims/aidl/IRcs.aidl",
"telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl",
"telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl",
"telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl",
@@ -578,7 +579,6 @@
"telephony/java/com/android/internal/telephony/euicc/ISetDefaultSmdpAddressCallback.aidl",
"telephony/java/com/android/internal/telephony/euicc/ISetNicknameCallback.aidl",
"telephony/java/com/android/internal/telephony/euicc/ISwitchToProfileCallback.aidl",
- "telephony/java/com/android/internal/telephony/rcs/IRcs.aidl",
"wifi/java/android/net/wifi/ISoftApCallback.aidl",
"wifi/java/android/net/wifi/IWifiManager.aidl",
"wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl",
@@ -1147,6 +1147,7 @@
metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " +
"--hide-package com.android.okhttp " +
"--hide-package com.android.org.conscrypt --hide-package com.android.server " +
+ "--error UnhiddenSystemApi " +
"--hide RequiresPermission " +
"--hide MissingPermission --hide BroadcastBehavior " +
"--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
@@ -1563,6 +1564,7 @@
dex_mapping_filename: "dex-mapping.txt",
args: metalava_framework_docs_args +
" --hide ReferencesHidden " +
+ " --hide UnhiddenSystemApi " +
" --show-unannotated " +
" --show-annotation android.annotation.SystemApi " +
" --show-annotation android.annotation.TestApi "
diff --git a/Android.mk b/Android.mk
index 92e33e9..e3cc275 100644
--- a/Android.mk
+++ b/Android.mk
@@ -72,6 +72,11 @@
$(hide) mkdir -p $(OUT_DOCS)/offline-sdk
( unzip -qo $< -d $(OUT_DOCS)/offline-sdk && touch -f $@ ) || exit 1
+# Run this for checkbuild
+checkbuild: doc-comment-check-docs
+# Check comment when you are updating the API
+update-api: doc-comment-check-docs
+
# ==== hiddenapi lists =======================================
.KATI_RESTAT: $(INTERNAL_PLATFORM_HIDDENAPI_FLAGS)
$(INTERNAL_PLATFORM_HIDDENAPI_FLAGS): \
diff --git a/api/current.txt b/api/current.txt
index d497c54..8f601cf 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -40855,7 +40855,9 @@
field public static final int SIOCGIFBRDADDR;
field public static final int SIOCGIFDSTADDR;
field public static final int SIOCGIFNETMASK;
+ field public static final int SOCK_CLOEXEC;
field public static final int SOCK_DGRAM;
+ field public static final int SOCK_NONBLOCK;
field public static final int SOCK_RAW;
field public static final int SOCK_SEQPACKET;
field public static final int SOCK_STREAM;
diff --git a/api/system-current.txt b/api/system-current.txt
index fd2e05e..5ef11a32 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5081,16 +5081,15 @@
public abstract class NetworkService extends android.app.Service {
ctor public NetworkService();
method protected abstract android.telephony.NetworkService.NetworkServiceProvider createNetworkServiceProvider(int);
- field public static final java.lang.String NETWORK_SERVICE_EXTRA_SLOT_ID = "android.telephony.extra.SLOT_ID";
field public static final java.lang.String NETWORK_SERVICE_INTERFACE = "android.telephony.NetworkService";
}
- public class NetworkService.NetworkServiceProvider {
+ public abstract class NetworkService.NetworkServiceProvider implements java.lang.AutoCloseable {
ctor public NetworkService.NetworkServiceProvider(int);
+ method public abstract void close();
method public void getNetworkRegistrationState(int, android.telephony.NetworkServiceCallback);
method public final int getSlotId();
method public final void notifyNetworkRegistrationStateChanged();
- method protected void onDestroy();
}
public class NetworkServiceCallback {
@@ -5427,20 +5426,19 @@
public abstract class DataService extends android.app.Service {
ctor public DataService();
method public abstract android.telephony.data.DataService.DataServiceProvider createDataServiceProvider(int);
- field public static final java.lang.String DATA_SERVICE_EXTRA_SLOT_ID = "android.telephony.data.extra.SLOT_ID";
field public static final java.lang.String DATA_SERVICE_INTERFACE = "android.telephony.data.DataService";
field public static final int REQUEST_REASON_HANDOVER = 3; // 0x3
field public static final int REQUEST_REASON_NORMAL = 1; // 0x1
field public static final int REQUEST_REASON_SHUTDOWN = 2; // 0x2
}
- public class DataService.DataServiceProvider {
+ public abstract class DataService.DataServiceProvider implements java.lang.AutoCloseable {
ctor public DataService.DataServiceProvider(int);
+ method public abstract void close();
method public void deactivateDataCall(int, int, android.telephony.data.DataServiceCallback);
method public void getDataCallList(android.telephony.data.DataServiceCallback);
method public final int getSlotId();
method public final void notifyDataCallListChanged(java.util.List<android.telephony.data.DataCallResponse>);
- method protected void onDestroy();
method public void setDataProfile(java.util.List<android.telephony.data.DataProfile>, boolean, android.telephony.data.DataServiceCallback);
method public void setInitialAttachApn(android.telephony.data.DataProfile, boolean, android.telephony.data.DataServiceCallback);
method public void setupDataCall(int, android.telephony.data.DataProfile, boolean, boolean, int, android.net.LinkProperties, android.telephony.data.DataServiceCallback);
@@ -5905,6 +5903,7 @@
field public static final int CODE_RADIO_SETUP_FAILURE = 1509; // 0x5e5
field public static final int CODE_RADIO_UPLINK_FAILURE = 1508; // 0x5e4
field public static final int CODE_REGISTRATION_ERROR = 1000; // 0x3e8
+ field public static final int CODE_REJECTED_ELSEWHERE = 1017; // 0x3f9
field public static final int CODE_REJECT_1X_COLLISION = 1603; // 0x643
field public static final int CODE_REJECT_CALL_ON_OTHER_SUB = 1602; // 0x642
field public static final int CODE_REJECT_CALL_TYPE_NOT_ALLOWED = 1605; // 0x645
@@ -5928,26 +5927,39 @@
field public static final int CODE_REJECT_VT_AVPF_NOT_ALLOWED = 1619; // 0x653
field public static final int CODE_REJECT_VT_TTY_NOT_ALLOWED = 1615; // 0x64f
field public static final int CODE_REMOTE_CALL_DECLINE = 1404; // 0x57c
+ field public static final int CODE_SESSION_MODIFICATION_FAILED = 1517; // 0x5ed
field public static final int CODE_SIP_ALTERNATE_EMERGENCY_CALL = 1514; // 0x5ea
+ field public static final int CODE_SIP_AMBIGUOUS = 376; // 0x178
field public static final int CODE_SIP_BAD_ADDRESS = 337; // 0x151
field public static final int CODE_SIP_BAD_REQUEST = 331; // 0x14b
field public static final int CODE_SIP_BUSY = 338; // 0x152
+ field public static final int CODE_SIP_CALL_OR_TRANS_DOES_NOT_EXIST = 372; // 0x174
field public static final int CODE_SIP_CLIENT_ERROR = 342; // 0x156
+ field public static final int CODE_SIP_EXTENSION_REQUIRED = 370; // 0x172
field public static final int CODE_SIP_FORBIDDEN = 332; // 0x14c
field public static final int CODE_SIP_GLOBAL_ERROR = 362; // 0x16a
+ field public static final int CODE_SIP_INTERVAL_TOO_BRIEF = 371; // 0x173
+ field public static final int CODE_SIP_LOOP_DETECTED = 373; // 0x175
+ field public static final int CODE_SIP_METHOD_NOT_ALLOWED = 366; // 0x16e
field public static final int CODE_SIP_NOT_ACCEPTABLE = 340; // 0x154
field public static final int CODE_SIP_NOT_FOUND = 333; // 0x14d
field public static final int CODE_SIP_NOT_REACHABLE = 341; // 0x155
field public static final int CODE_SIP_NOT_SUPPORTED = 334; // 0x14e
+ field public static final int CODE_SIP_PROXY_AUTHENTICATION_REQUIRED = 367; // 0x16f
field public static final int CODE_SIP_REDIRECTED = 321; // 0x141
field public static final int CODE_SIP_REQUEST_CANCELLED = 339; // 0x153
+ field public static final int CODE_SIP_REQUEST_ENTITY_TOO_LARGE = 368; // 0x170
+ field public static final int CODE_SIP_REQUEST_PENDING = 377; // 0x179
field public static final int CODE_SIP_REQUEST_TIMEOUT = 335; // 0x14f
+ field public static final int CODE_SIP_REQUEST_URI_TOO_LARGE = 369; // 0x171
field public static final int CODE_SIP_SERVER_ERROR = 354; // 0x162
field public static final int CODE_SIP_SERVER_INTERNAL_ERROR = 351; // 0x15f
field public static final int CODE_SIP_SERVER_TIMEOUT = 353; // 0x161
field public static final int CODE_SIP_SERVICE_UNAVAILABLE = 352; // 0x160
field public static final int CODE_SIP_TEMPRARILY_UNAVAILABLE = 336; // 0x150
+ field public static final int CODE_SIP_TOO_MANY_HOPS = 374; // 0x176
field public static final int CODE_SIP_TRANSACTION_DOES_NOT_EXIST = 343; // 0x157
+ field public static final int CODE_SIP_UNDECIPHERABLE = 378; // 0x17a
field public static final int CODE_SIP_USER_MARKED_UNWANTED = 365; // 0x16d
field public static final int CODE_SIP_USER_REJECTED = 361; // 0x169
field public static final int CODE_SUPP_SVC_CANCELLED = 1202; // 0x4b2
@@ -5957,9 +5969,11 @@
field public static final int CODE_TIMEOUT_NO_ANSWER = 202; // 0xca
field public static final int CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE = 203; // 0xcb
field public static final int CODE_UNSPECIFIED = 0; // 0x0
+ field public static final int CODE_USER_CANCELLED_SESSION_MODIFICATION = 512; // 0x200
field public static final int CODE_USER_DECLINE = 504; // 0x1f8
field public static final int CODE_USER_IGNORE = 503; // 0x1f7
field public static final int CODE_USER_NOANSWER = 502; // 0x1f6
+ field public static final int CODE_USER_REJECTED_SESSION_MODIFICATION = 511; // 0x1ff
field public static final int CODE_USER_TERMINATED = 501; // 0x1f5
field public static final int CODE_USER_TERMINATED_BY_REMOTE = 510; // 0x1fe
field public static final int CODE_UT_CB_PASSWORD_MISMATCH = 821; // 0x335
diff --git a/cmds/statsd/src/atom_field_options.proto b/cmds/statsd/src/atom_field_options.proto
index a2a03b1..7dfe7d6 100644
--- a/cmds/statsd/src/atom_field_options.proto
+++ b/cmds/statsd/src/atom_field_options.proto
@@ -64,10 +64,22 @@
optional StateField option = 1 [default = STATE_FIELD_UNSET];
}
+// Used to generate StatsLog.write APIs.
+enum LogMode {
+ MODE_UNSET = 0;
+ // Log fields as their actual types e.g., all primary data types.
+ // Or fields that are hardcoded in stats_log_api_gen tool e.g., AttributionNode
+ MODE_AUTOMATIC = 1;
+ // Log fields in their proto binary format. These fields will not be parsed in statsd
+ MODE_BYTES = 2;
+}
+
extend google.protobuf.FieldOptions {
// Flags to decorate an atom that presents a state change.
optional StateAtomFieldOption stateFieldOption = 50000;
// Flags to decorate the uid fields in an atom.
optional bool is_uid = 50001 [default = false];
+
+ optional LogMode log_mode = 50002 [default = MODE_AUTOMATIC];
}
\ No newline at end of file
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 281f900..d9fa0f1 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -26,6 +26,7 @@
import "frameworks/base/core/proto/android/bluetooth/enums.proto";
import "frameworks/base/core/proto/android/os/enums.proto";
import "frameworks/base/core/proto/android/server/enums.proto";
+import "frameworks/base/core/proto/android/stats/launcher/launcher.proto";
import "frameworks/base/core/proto/android/telecomm/enums.proto";
import "frameworks/base/core/proto/android/telephony/enums.proto";
import "frameworks/base/core/proto/android/view/enums.proto";
@@ -59,7 +60,8 @@
LongPartialWakelockStateChanged long_partial_wakelock_state_changed = 11;
MobileRadioPowerStateChanged mobile_radio_power_state_changed = 12;
WifiRadioPowerStateChanged wifi_radio_power_state_changed = 13;
- // 14 - 19 are available
+ // 14 - 18 are available
+ LauncherUIChanged launcher_event = 19;
BatterySaverModeStateChanged battery_saver_mode_state_changed = 20;
DeviceIdleModeStateChanged device_idle_mode_state_changed = 21;
DeviceIdlingModeStateChanged device_idling_mode_state_changed = 22;
@@ -1166,6 +1168,14 @@
optional State state = 1;
}
+message LauncherUIChanged {
+ optional android.stats.launcher.LauncherAction action = 1;
+ optional android.stats.launcher.LauncherState src_state = 2;
+ optional android.stats.launcher.LauncherState dst_state = 3;
+ optional android.stats.launcher.LauncherExtension extension = 4 [(log_mode) = MODE_BYTES];
+ optional bool is_swipe_up_enabled = 5;
+}
+
/**
* Logs that a setting was updated.
* Logged from:
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 4e4f146..5d6d02b 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -379,7 +379,7 @@
string LogEvent::ToString() const {
string result;
- result += StringPrintf("{ %lld %lld (%d)", (long long)mLogdTimestampNs,
+ result += StringPrintf("{ uid(%d) %lld %lld (%d)", mLogUid, (long long)mLogdTimestampNs,
(long long)mElapsedTimestampNs, mTagId);
for (const auto& value : mValues) {
result +=
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index a0ab3e4..11ce717 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -25,15 +25,16 @@
#include <utils/Log.h>
#include <utils/SystemClock.h>
+using android::util::AtomsInfo;
using android::util::FIELD_COUNT_REPEATED;
using android::util::FIELD_TYPE_BOOL;
+using android::util::FIELD_TYPE_FIXED64;
using android::util::FIELD_TYPE_FLOAT;
using android::util::FIELD_TYPE_INT32;
using android::util::FIELD_TYPE_INT64;
-using android::util::FIELD_TYPE_UINT64;
-using android::util::FIELD_TYPE_FIXED64;
using android::util::FIELD_TYPE_MESSAGE;
using android::util::FIELD_TYPE_STRING;
+using android::util::FIELD_TYPE_UINT64;
using android::util::ProtoOutputStream;
namespace android {
@@ -294,8 +295,9 @@
// }
//
//
-void writeFieldValueTreeToStreamHelper(const std::vector<FieldValue>& dims, size_t* index,
- int depth, int prefix, ProtoOutputStream* protoOutput) {
+void writeFieldValueTreeToStreamHelper(int tagId, const std::vector<FieldValue>& dims,
+ size_t* index, int depth, int prefix,
+ ProtoOutputStream* protoOutput) {
size_t count = dims.size();
while (*index < count) {
const auto& dim = dims[*index];
@@ -319,9 +321,33 @@
case FLOAT:
protoOutput->write(FIELD_TYPE_FLOAT | fieldNum, dim.mValue.float_value);
break;
- case STRING:
- protoOutput->write(FIELD_TYPE_STRING | fieldNum, dim.mValue.str_value);
+ case STRING: {
+ bool isBytesField = false;
+ // Bytes field is logged via string format in log_msg format. So here we check
+ // if this string field is a byte field.
+ std::map<int, std::vector<int>>::const_iterator itr;
+ if (depth == 0 && (itr = AtomsInfo::kBytesFieldAtoms.find(tagId)) !=
+ AtomsInfo::kBytesFieldAtoms.end()) {
+ const std::vector<int>& bytesFields = itr->second;
+ for (int bytesField : bytesFields) {
+ if (bytesField == fieldNum) {
+ // This is a bytes field
+ isBytesField = true;
+ break;
+ }
+ }
+ }
+ if (isBytesField) {
+ if (dim.mValue.str_value.length() > 0) {
+ protoOutput->write(FIELD_TYPE_MESSAGE | fieldNum,
+ (const char*)dim.mValue.str_value.c_str(),
+ dim.mValue.str_value.length());
+ }
+ } else {
+ protoOutput->write(FIELD_TYPE_STRING | fieldNum, dim.mValue.str_value);
+ }
break;
+ }
default:
break;
}
@@ -337,7 +363,7 @@
}
// Directly jump to the leaf value because the repeated position field is implied
// by the position of the sub msg in the parent field.
- writeFieldValueTreeToStreamHelper(dims, index, valueDepth,
+ writeFieldValueTreeToStreamHelper(tagId, dims, index, valueDepth,
dim.mField.getPrefix(valueDepth), protoOutput);
if (msg_token != 0) {
protoOutput->end(msg_token);
@@ -354,7 +380,7 @@
uint64_t atomToken = protoOutput->start(FIELD_TYPE_MESSAGE | tagId);
size_t index = 0;
- writeFieldValueTreeToStreamHelper(values, &index, 0, 0, protoOutput);
+ writeFieldValueTreeToStreamHelper(tagId, values, &index, 0, 0, protoOutput);
protoOutput->end(atomToken);
}
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
index 2fcde29..b29de53 100644
--- a/cmds/statsd/tests/LogEvent_test.cpp
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -12,9 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "src/logd/LogEvent.h"
#include <gtest/gtest.h>
#include <log/log_event_list.h>
-#include "src/logd/LogEvent.h"
+#include "frameworks/base/cmds/statsd/src/atoms.pb.h"
+#include "frameworks/base/core/proto/android/stats/launcher/launcher.pb.h"
#ifdef __ANDROID__
@@ -22,6 +24,9 @@
namespace os {
namespace statsd {
+using std::string;
+using util::ProtoOutputStream;
+
TEST(LogEventTest, TestLogParsing) {
LogEvent event1(1, 2000);
@@ -159,6 +164,94 @@
}
+TEST(LogEventTest, TestBinaryFieldAtom) {
+ Atom launcherAtom;
+ auto launcher_event = launcherAtom.mutable_launcher_event();
+ launcher_event->set_action(stats::launcher::LauncherAction::LONGPRESS);
+ launcher_event->set_src_state(stats::launcher::LauncherState::OVERVIEW);
+ launcher_event->set_dst_state(stats::launcher::LauncherState::ALLAPPS);
+
+ auto extension = launcher_event->mutable_extension();
+
+ auto src_target = extension->add_src_target();
+ src_target->set_type(stats::launcher::LauncherTarget_Type_ITEM_TYPE);
+ src_target->set_item(stats::launcher::LauncherTarget_Item_FOLDER_ICON);
+
+ auto dst_target = extension->add_dst_target();
+ dst_target->set_type(stats::launcher::LauncherTarget_Type_ITEM_TYPE);
+ dst_target->set_item(stats::launcher::LauncherTarget_Item_WIDGET);
+
+ string extension_str;
+ extension->SerializeToString(&extension_str);
+
+ LogEvent event1(Atom::kLauncherEventFieldNumber, 1000);
+
+ event1.write((int32_t)stats::launcher::LauncherAction::LONGPRESS);
+ event1.write((int32_t)stats::launcher::LauncherState::OVERVIEW);
+ event1.write((int64_t)stats::launcher::LauncherState::ALLAPPS);
+ event1.write(extension_str);
+ event1.init();
+
+ ProtoOutputStream proto;
+ event1.ToProto(proto);
+
+ std::vector<uint8_t> outData;
+ outData.resize(proto.size());
+ size_t pos = 0;
+ auto iter = proto.data();
+ while (iter.readBuffer() != NULL) {
+ size_t toRead = iter.currentToRead();
+ std::memcpy(&(outData[pos]), iter.readBuffer(), toRead);
+ pos += toRead;
+ iter.rp()->move(toRead);
+ }
+
+ std::string result_str(outData.begin(), outData.end());
+ std::string orig_str;
+ launcherAtom.SerializeToString(&orig_str);
+
+ EXPECT_EQ(orig_str, result_str);
+}
+
+TEST(LogEventTest, TestBinaryFieldAtom_empty) {
+ Atom launcherAtom;
+ auto launcher_event = launcherAtom.mutable_launcher_event();
+ launcher_event->set_action(stats::launcher::LauncherAction::LONGPRESS);
+ launcher_event->set_src_state(stats::launcher::LauncherState::OVERVIEW);
+ launcher_event->set_dst_state(stats::launcher::LauncherState::ALLAPPS);
+
+ // empty string.
+ string extension_str;
+
+ LogEvent event1(Atom::kLauncherEventFieldNumber, 1000);
+
+ event1.write((int32_t)stats::launcher::LauncherAction::LONGPRESS);
+ event1.write((int32_t)stats::launcher::LauncherState::OVERVIEW);
+ event1.write((int64_t)stats::launcher::LauncherState::ALLAPPS);
+ event1.write(extension_str);
+ event1.init();
+
+ ProtoOutputStream proto;
+ event1.ToProto(proto);
+
+ std::vector<uint8_t> outData;
+ outData.resize(proto.size());
+ size_t pos = 0;
+ auto iter = proto.data();
+ while (iter.readBuffer() != NULL) {
+ size_t toRead = iter.currentToRead();
+ std::memcpy(&(outData[pos]), iter.readBuffer(), toRead);
+ pos += toRead;
+ iter.rp()->move(toRead);
+ }
+
+ std::string result_str(outData.begin(), outData.end());
+ std::string orig_str;
+ launcherAtom.SerializeToString(&orig_str);
+
+ EXPECT_EQ(orig_str, result_str);
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/config/dirty-image-objects b/config/dirty-image-objects
index 9b4d199..9e2230b 100644
--- a/config/dirty-image-objects
+++ b/config/dirty-image-objects
@@ -44,7 +44,6 @@
sun.misc.FormattedFloatingDecimal
java.util.stream.IntStream
android.icu.util.TimeZone
-libcore.io.DropBox
org.apache.harmony.luni.internal.util.TimezoneGetter
dalvik.system.SocketTagger
dalvik.system.CloseGuard
@@ -137,7 +136,6 @@
android.icu.util.ULocale
dalvik.system.BaseDexClassLoader
android.icu.text.BreakIterator
-libcore.io.EventLogger
libcore.net.NetworkSecurityPolicy
android.icu.text.UnicodeSet
com.android.org.conscrypt.TrustedCertificateStore$PreloadHolder
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 2aeb431..30e9bfb 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -2938,7 +2938,6 @@
Lcom/android/internal/telephony/dataconnection/DataConnection;->mActiveState:Lcom/android/internal/telephony/dataconnection/DataConnection$DcActiveState;
Lcom/android/internal/telephony/dataconnection/DataConnection;->mConnectionParams:Lcom/android/internal/telephony/dataconnection/DataConnection$ConnectionParams;
Lcom/android/internal/telephony/dataconnection/DataConnection;->mDataRegState:I
-Lcom/android/internal/telephony/dataconnection/DataConnection;->mDcFailCause:Lcom/android/internal/telephony/dataconnection/DcFailCause;
Lcom/android/internal/telephony/dataconnection/DataConnection;->mDct:Lcom/android/internal/telephony/dataconnection/DcTracker;
Lcom/android/internal/telephony/dataconnection/DataConnection;->mDisconnectingErrorCreatingConnection:Lcom/android/internal/telephony/dataconnection/DataConnection$DcDisconnectionErrorCreatingConnection;
Lcom/android/internal/telephony/dataconnection/DataConnection;->mDisconnectingState:Lcom/android/internal/telephony/dataconnection/DataConnection$DcDisconnectingState;
@@ -2949,10 +2948,8 @@
Lcom/android/internal/telephony/dataconnection/DataConnection;->mNetworkInfo:Landroid/net/NetworkInfo;
Lcom/android/internal/telephony/dataconnection/DataConnection;->mPhone:Lcom/android/internal/telephony/Phone;
Lcom/android/internal/telephony/dataconnection/DataConnection;->mRilRat:I
-Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyAllDisconnectCompleted(Lcom/android/internal/telephony/dataconnection/DcFailCause;)V
Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyAllOfConnected(Ljava/lang/String;)V
Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyAllOfDisconnectDcRetrying(Ljava/lang/String;)V
-Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyConnectCompleted(Lcom/android/internal/telephony/dataconnection/DataConnection$ConnectionParams;Lcom/android/internal/telephony/dataconnection/DcFailCause;Z)V
Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyDisconnectCompleted(Lcom/android/internal/telephony/dataconnection/DataConnection$DisconnectParams;Z)V
Lcom/android/internal/telephony/dataconnection/DataConnection;->onConnect(Lcom/android/internal/telephony/dataconnection/DataConnection$ConnectionParams;)V
Lcom/android/internal/telephony/dataconnection/DataConnection;->tearDownData(Ljava/lang/Object;)V
@@ -2961,22 +2958,6 @@
Lcom/android/internal/telephony/dataconnection/DcController;->mDcListActiveByCid:Ljava/util/HashMap;
Lcom/android/internal/telephony/dataconnection/DcController;->mDct:Lcom/android/internal/telephony/dataconnection/DcTracker;
Lcom/android/internal/telephony/dataconnection/DcController;->mDcTesterDeactivateAll:Lcom/android/internal/telephony/dataconnection/DcTesterDeactivateAll;
-Lcom/android/internal/telephony/dataconnection/DcFailCause;->ACTIVATION_REJECT_GGSN:Lcom/android/internal/telephony/dataconnection/DcFailCause;
-Lcom/android/internal/telephony/dataconnection/DcFailCause;->ACTIVATION_REJECT_UNSPECIFIED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
-Lcom/android/internal/telephony/dataconnection/DcFailCause;->APN_TYPE_CONFLICT:Lcom/android/internal/telephony/dataconnection/DcFailCause;
-Lcom/android/internal/telephony/dataconnection/DcFailCause;->INSUFFICIENT_RESOURCES:Lcom/android/internal/telephony/dataconnection/DcFailCause;
-Lcom/android/internal/telephony/dataconnection/DcFailCause;->MISSING_UNKNOWN_APN:Lcom/android/internal/telephony/dataconnection/DcFailCause;
-Lcom/android/internal/telephony/dataconnection/DcFailCause;->NSAPI_IN_USE:Lcom/android/internal/telephony/dataconnection/DcFailCause;
-Lcom/android/internal/telephony/dataconnection/DcFailCause;->ONLY_IPV4_ALLOWED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
-Lcom/android/internal/telephony/dataconnection/DcFailCause;->ONLY_IPV6_ALLOWED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
-Lcom/android/internal/telephony/dataconnection/DcFailCause;->ONLY_SINGLE_BEARER_ALLOWED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
-Lcom/android/internal/telephony/dataconnection/DcFailCause;->OPERATOR_BARRED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
-Lcom/android/internal/telephony/dataconnection/DcFailCause;->PROTOCOL_ERRORS:Lcom/android/internal/telephony/dataconnection/DcFailCause;
-Lcom/android/internal/telephony/dataconnection/DcFailCause;->SERVICE_OPTION_NOT_SUBSCRIBED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
-Lcom/android/internal/telephony/dataconnection/DcFailCause;->SERVICE_OPTION_NOT_SUPPORTED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
-Lcom/android/internal/telephony/dataconnection/DcFailCause;->SERVICE_OPTION_OUT_OF_ORDER:Lcom/android/internal/telephony/dataconnection/DcFailCause;
-Lcom/android/internal/telephony/dataconnection/DcFailCause;->UNKNOWN_PDP_ADDRESS_TYPE:Lcom/android/internal/telephony/dataconnection/DcFailCause;
-Lcom/android/internal/telephony/dataconnection/DcFailCause;->USER_AUTHENTICATION:Lcom/android/internal/telephony/dataconnection/DcFailCause;
Lcom/android/internal/telephony/dataconnection/DcTracker$RecoveryAction;->isAggressiveRecovery(I)Z
Lcom/android/internal/telephony/dataconnection/DcTracker;->cancelReconnectAlarm(Lcom/android/internal/telephony/dataconnection/ApnContext;)V
Lcom/android/internal/telephony/dataconnection/DcTracker;->cleanUpAllConnections(Ljava/lang/String;)V
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 495615b..fafcc6b 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -6124,12 +6124,6 @@
libcore.io.ClassPathURLStreamHandler
libcore.io.ClassPathURLStreamHandler$ClassPathURLConnection
libcore.io.ClassPathURLStreamHandler$ClassPathURLConnection$1
-libcore.io.DropBox
-libcore.io.DropBox$DefaultReporter
-libcore.io.DropBox$Reporter
-libcore.io.EventLogger
-libcore.io.EventLogger$DefaultReporter
-libcore.io.EventLogger$Reporter
libcore.io.ForwardingOs
libcore.io.IoBridge
libcore.io.IoTracker
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 47fddfe..15af8a9 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -81,7 +81,6 @@
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
-import android.os.DropBoxManager;
import android.os.Environment;
import android.os.GraphicsEnvironment;
import android.os.Handler;
@@ -157,8 +156,6 @@
import dalvik.system.VMDebug;
import dalvik.system.VMRuntime;
-import libcore.io.DropBox;
-import libcore.io.EventLogger;
import libcore.io.IoUtils;
import libcore.net.event.NetworkEventDispatcher;
@@ -6680,9 +6677,6 @@
}
}
- // add dropbox logging to libcore
- DropBox.setReporter(new DropBoxReporter());
-
ViewRootImpl.ConfigChangedCallback configChangedCallback
= (Configuration globalConfig) -> {
synchronized (mResourcesManager) {
@@ -6736,38 +6730,6 @@
}
}
- private static class EventLoggingReporter implements EventLogger.Reporter {
- @Override
- public void report (int code, Object... list) {
- EventLog.writeEvent(code, list);
- }
- }
-
- private class DropBoxReporter implements DropBox.Reporter {
-
- private DropBoxManager dropBox;
-
- public DropBoxReporter() {}
-
- @Override
- public void addData(String tag, byte[] data, int flags) {
- ensureInitialized();
- dropBox.addData(tag, data, flags);
- }
-
- @Override
- public void addText(String tag, String data) {
- ensureInitialized();
- dropBox.addText(tag, data);
- }
-
- private synchronized void ensureInitialized() {
- if (dropBox == null) {
- dropBox = (DropBoxManager) getSystemContext().getSystemService(Context.DROPBOX_SERVICE);
- }
- }
- }
-
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
@@ -6778,9 +6740,6 @@
Environment.initForCurrentUser();
- // Set the reporter for event logging in libcore
- EventLogger.setReporter(new EventLoggingReporter());
-
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 83c43e7..b976d3f 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -143,7 +143,7 @@
import android.telephony.TelephonyManager;
import android.telephony.euicc.EuiccCardManager;
import android.telephony.euicc.EuiccManager;
-import android.telephony.rcs.RcsManager;
+import android.telephony.ims.RcsManager;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java
index 66d7a25..b1465ae 100644
--- a/core/java/android/app/VrManager.java
+++ b/core/java/android/app/VrManager.java
@@ -4,7 +4,6 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@@ -230,7 +229,6 @@
* input by InputMethodManagerService.
* @hide
*/
- @TestApi
@RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
public void setVrInputMethod(ComponentName componentName) {
try {
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 654bfaf..10c8b15 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -643,6 +643,7 @@
private final IBluetoothManager mManagerService;
@UnsupportedAppUsage
private IBluetooth mService;
+ private Context mContext;
private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
private final Object mLock = new Object();
@@ -1541,6 +1542,23 @@
}
/**
+ * Set the context for this BluetoothAdapter (only called from BluetoothManager)
+ * @hide
+ */
+ public void setContext(Context context) {
+ mContext = context;
+ }
+
+ private String getOpPackageName() {
+ // Workaround for legacy API for getting a BluetoothAdapter not
+ // passing a context
+ if (mContext != null) {
+ return mContext.getOpPackageName();
+ }
+ return ActivityThread.currentOpPackageName();
+ }
+
+ /**
* Start the remote device discovery process.
* <p>The discovery process usually involves an inquiry scan of about 12
* seconds, followed by a page scan of each new device to retrieve its
@@ -1577,7 +1595,7 @@
try {
mServiceLock.readLock().lock();
if (mService != null) {
- return mService.startDiscovery();
+ return mService.startDiscovery(getOpPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "", e);
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index e3672a7..e08d405 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -67,6 +67,7 @@
}
// Legacy api - getDefaultAdapter does not take in the context
mAdapter = BluetoothAdapter.getDefaultAdapter();
+ mAdapter.setContext(context);
}
/**
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index d3d07bd..72795cf 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4260,7 +4260,7 @@
/**
* Use with {@link #getSystemService(String)} to retrieve an
- * {@link android.telephony.rcs.RcsManager}.
+ * {@link android.telephony.ims.RcsManager}.
* @hide
*/
public static final String TELEPHONY_RCS_SERVICE = "ircs";
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index d457a1b..a03e929 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -327,11 +327,13 @@
return false;
}
- if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) {
+ int dupFlags = (fd_flags & FD_CLOEXEC) ? O_CLOEXEC : 0;
+ if (TEMP_FAILURE_RETRY(dup3(new_fd, fd, dupFlags)) == -1) {
close(new_fd);
- *error_msg = android::base::StringPrintf("Failed dup2(%d, %d) (%s): %s",
+ *error_msg = android::base::StringPrintf("Failed dup3(%d, %d, %d) (%s): %s",
fd,
new_fd,
+ dupFlags,
file_path.c_str(),
strerror(errno));
return false;
diff --git a/core/proto/android/stats/launcher/launcher.proto b/core/proto/android/stats/launcher/launcher.proto
new file mode 100644
index 0000000..dbd0e03
--- /dev/null
+++ b/core/proto/android/stats/launcher/launcher.proto
@@ -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.
+ */
+
+syntax = "proto2";
+package android.stats.launcher;
+option java_multiple_files = true;
+
+enum LauncherAction {
+ DEFAULT_ACTION = 0;
+ LAUNCH_APP = 1;
+ LAUNCH_TASK = 2;
+ DISMISS_TASK = 3;
+ LONGPRESS = 4;
+ DRAGDROP = 5;
+ SWIPE_UP = 6;
+ SWIPE_DOWN = 7;
+ SWIPE_LEFT = 8;
+ SWIPE_RIGHT = 9;
+}
+
+enum LauncherState {
+ BACKGROUND = 0;
+ HOME = 1;
+ OVERVIEW = 2;
+ ALLAPPS = 3;
+}
+
+message LauncherTarget {
+ enum Type {
+ NONE = 0;
+ ITEM_TYPE = 1;
+ CONTROL_TYPE = 2;
+ CONTAINER_TYPE = 3;
+ }
+ enum Item {
+ DEFAULT_ITEM = 0;
+ APP_ICON = 1;
+ SHORTCUT = 2;
+ WIDGET = 3;
+ FOLDER_ICON = 4;
+ DEEPSHORTCUT = 5;
+ SEARCHBOX = 6;
+ EDITTEXT = 7;
+ NOTIFICATION = 8;
+ TASK = 9;
+ }
+ enum Container {
+ DEFAULT_CONTAINER = 0;
+ HOTSEAT = 1;
+ FOLDER = 2;
+ PREDICTION = 3;
+ SEARCHRESULT = 4;
+ }
+ enum Control {
+ DEFAULT_CONTROL = 0;
+ MENU = 1;
+ UNINSTALL = 2;
+ REMOVE = 3;
+ }
+ optional Type type = 1;
+ optional Item item = 2;
+ optional Container container = 3;
+ optional Control control = 4;
+ optional string launch_component = 5;
+ optional int32 page_id = 6;
+ optional int32 grid_x = 7;
+ optional int32 grid_y = 8;
+}
+
+message LauncherExtension {
+ repeated LauncherTarget src_target = 1;
+ repeated LauncherTarget dst_target = 2;
+}
diff --git a/data/etc/OWNERS b/data/etc/OWNERS
index bbec474..ea66ee3 100644
--- a/data/etc/OWNERS
+++ b/data/etc/OWNERS
@@ -1 +1 @@
-per-file privapp-permissions-platform.xml = hackbod@android.com, jsharkey@android.com, svetoslavganov@google.com, toddke@google.com, yamasani@google.com
+per-file privapp-permissions-platform.xml = hackbod@android.com, jsharkey@android.com, svetoslavganov@google.com, toddke@google.com, yamasani@google.com, cbrubaker@google.com, jeffv@google.com, moltmann@google.com
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/UserManagerHelper.java b/packages/SettingsLib/src/com/android/settingslib/users/UserManagerHelper.java
index 4c45a75..cb2a088 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/UserManagerHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/UserManagerHelper.java
@@ -25,9 +25,9 @@
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
+import android.sysprop.CarProperties;
import android.util.Log;
import com.android.internal.util.UserIcons;
@@ -43,7 +43,6 @@
@Deprecated
public final class UserManagerHelper {
private static final String TAG = "UserManagerHelper";
- private static final String HEADLESS_SYSTEM_USER = "android.car.systemuser.headless";
private final Context mContext;
private final UserManager mUserManager;
private final ActivityManager mActivityManager;
@@ -84,7 +83,7 @@
* @return {@boolean true} if headless system user.
*/
public boolean isHeadlessSystemUser() {
- return SystemProperties.getBoolean(HEADLESS_SYSTEM_USER, false);
+ return CarProperties.headless_system_user().orElse(false);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 83021ca..be46d2c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -19,7 +19,7 @@
import android.app.ActivityManager;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
-import android.os.SystemProperties;
+import android.sysprop.CarProperties;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
@@ -56,7 +56,7 @@
CarBatteryController.BatteryViewHandler {
private static final String TAG = "CarStatusBar";
public static final boolean ENABLE_HVAC_CONNECTION
- = !SystemProperties.getBoolean("android.car.hvac.demo", true);
+ = !CarProperties.hvac_demo().orElse(true);
private TaskStackListenerImpl mTaskStackListener;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index eda9fe1..89194e4 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1968,6 +1968,7 @@
void systemReady() {
mProxyTracker.loadGlobalProxy();
registerNetdEventCallback();
+ mTethering.systemReady();
synchronized (this) {
mSystemReady = true;
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index d0e8b47..0f00c11 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -163,8 +163,6 @@
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)}.
@@ -954,8 +952,7 @@
public String[] listInterfaces() {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
- final List<String> result = mNetdService.interfaceGetList();
- return result.toArray(EMPTY_STRING_ARRAY);
+ return mNetdService.interfaceGetList();
} catch (RemoteException | ServiceSpecificException e) {
throw new IllegalStateException(e);
}
@@ -1247,8 +1244,7 @@
public String[] listTetheredInterfaces() {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
- final List<String> result = mNetdService.tetherInterfaceList();
- return result.toArray(EMPTY_STRING_ARRAY);
+ return mNetdService.tetherInterfaceList();
} catch (RemoteException | ServiceSpecificException e) {
throw new IllegalStateException(e);
}
@@ -1271,8 +1267,7 @@
public String[] getDnsForwarders() {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
- final List<String> result = mNetdService.tetherDnsList();
- return result.toArray(EMPTY_STRING_ARRAY);
+ return mNetdService.tetherDnsList();
} catch (RemoteException | ServiceSpecificException e) {
throw new IllegalStateException(e);
}
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index d75601b..9dfdddb 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -1382,7 +1382,7 @@
return;
}
- mUpstreamNetworkMonitor.start(mDeps.getDefaultNetworkRequest());
+ mUpstreamNetworkMonitor.startObserveAllNetworks();
// TODO: De-duplicate with updateUpstreamWanted() below.
if (upstreamWanted()) {
@@ -1658,6 +1658,10 @@
}
}
+ public void systemReady() {
+ mUpstreamNetworkMonitor.startTrackDefaultNetwork(mDeps.getDefaultNetworkRequest());
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
// Binder.java closes the resource for us.
diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index 3e5d5aa..3ac311b 100644
--- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -55,10 +55,13 @@
* A class to centralize all the network and link properties information
* pertaining to the current and any potential upstream network.
*
- * Calling #start() registers two callbacks: one to track the system default
- * network and a second to observe all networks. The latter is necessary
- * while the expression of preferred upstreams remains a list of legacy
- * connectivity types. In future, this can be revisited.
+ * The owner of UNM gets it to register network callbacks by calling the
+ * following methods :
+ * Calling #startTrackDefaultNetwork() to track the system default network.
+ * Calling #startObserveAllNetworks() to observe all networks. Listening all
+ * networks is necessary while the expression of preferred upstreams remains
+ * a list of legacy connectivity types. In future, this can be revisited.
+ * Calling #registerMobileNetworkRequest() to bring up mobile DUN/HIPRI network.
*
* The methods and data members of this class are only to be accessed and
* modified from the tethering master state machine thread. Any other
@@ -119,33 +122,31 @@
mCM = cm;
}
- public void start(NetworkRequest defaultNetworkRequest) {
- stop();
-
- final NetworkRequest listenAllRequest = new NetworkRequest.Builder()
- .clearCapabilities().build();
- mListenAllCallback = new UpstreamNetworkCallback(CALLBACK_LISTEN_ALL);
- cm().registerNetworkCallback(listenAllRequest, mListenAllCallback, mHandler);
-
- if (defaultNetworkRequest != null) {
- // This is not really a "request", just a way of tracking the system default network.
- // It's guaranteed not to actually bring up any networks because it's the same request
- // as the ConnectivityService default request, and thus shares fate with it. We can't
- // use registerDefaultNetworkCallback because it will not track the system default
- // network if there is a VPN that applies to our UID.
+ public void startTrackDefaultNetwork(NetworkRequest defaultNetworkRequest) {
+ // This is not really a "request", just a way of tracking the system default network.
+ // It's guaranteed not to actually bring up any networks because it's the same request
+ // as the ConnectivityService default request, and thus shares fate with it. We can't
+ // use registerDefaultNetworkCallback because it will not track the system default
+ // network if there is a VPN that applies to our UID.
+ if (mDefaultNetworkCallback == null) {
final NetworkRequest trackDefaultRequest = new NetworkRequest(defaultNetworkRequest);
mDefaultNetworkCallback = new UpstreamNetworkCallback(CALLBACK_DEFAULT_INTERNET);
cm().requestNetwork(trackDefaultRequest, mDefaultNetworkCallback, mHandler);
}
}
+ public void startObserveAllNetworks() {
+ stop();
+
+ final NetworkRequest listenAllRequest = new NetworkRequest.Builder()
+ .clearCapabilities().build();
+ mListenAllCallback = new UpstreamNetworkCallback(CALLBACK_LISTEN_ALL);
+ cm().registerNetworkCallback(listenAllRequest, mListenAllCallback, mHandler);
+ }
+
public void stop() {
releaseMobileNetworkRequest();
- releaseCallback(mDefaultNetworkCallback);
- mDefaultNetworkCallback = null;
- mDefaultInternetNetwork = null;
-
releaseCallback(mListenAllCallback);
mListenAllCallback = null;
@@ -264,9 +265,7 @@
mNetworkMap.put(network, new NetworkState(null, null, null, network, null, null));
}
- private void handleNetCap(int callbackType, Network network, NetworkCapabilities newNc) {
- if (callbackType == CALLBACK_DEFAULT_INTERNET) mDefaultInternetNetwork = network;
-
+ private void handleNetCap(Network network, NetworkCapabilities newNc) {
final NetworkState prev = mNetworkMap.get(network);
if (prev == null || newNc.equals(prev.networkCapabilities)) {
// Ignore notifications about networks for which we have not yet
@@ -315,31 +314,25 @@
notifyTarget(EVENT_ON_LINKPROPERTIES, network);
}
- private void handleSuspended(int callbackType, Network network) {
- if (callbackType != CALLBACK_LISTEN_ALL) return;
+ private void handleSuspended(Network network) {
if (!network.equals(mTetheringUpstreamNetwork)) return;
mLog.log("SUSPENDED current upstream: " + network);
}
- private void handleResumed(int callbackType, Network network) {
- if (callbackType != CALLBACK_LISTEN_ALL) return;
+ private void handleResumed(Network network) {
if (!network.equals(mTetheringUpstreamNetwork)) return;
mLog.log("RESUMED current upstream: " + network);
}
- private void handleLost(int callbackType, Network network) {
- if (network.equals(mDefaultInternetNetwork)) {
- mDefaultInternetNetwork = null;
- // There are few TODOs within ConnectivityService's rematching code
- // pertaining to spurious onLost() notifications.
- //
- // TODO: simplify this, probably if favor of code that:
- // - selects a new upstream if mTetheringUpstreamNetwork has
- // been lost (by any callback)
- // - deletes the entry from the map only when the LISTEN_ALL
- // callback gets notified.
- if (callbackType == CALLBACK_DEFAULT_INTERNET) return;
- }
+ private void handleLost(Network network) {
+ // There are few TODOs within ConnectivityService's rematching code
+ // pertaining to spurious onLost() notifications.
+ //
+ // TODO: simplify this, probably if favor of code that:
+ // - selects a new upstream if mTetheringUpstreamNetwork has
+ // been lost (by any callback)
+ // - deletes the entry from the map only when the LISTEN_ALL
+ // callback gets notified.
if (!mNetworkMap.containsKey(network)) {
// Ignore loss of networks about which we had not previously
@@ -393,11 +386,17 @@
@Override
public void onCapabilitiesChanged(Network network, NetworkCapabilities newNc) {
- handleNetCap(mCallbackType, network, newNc);
+ if (mCallbackType == CALLBACK_DEFAULT_INTERNET) {
+ mDefaultInternetNetwork = network;
+ return;
+ }
+ handleNetCap(network, newNc);
}
@Override
public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
+ if (mCallbackType == CALLBACK_DEFAULT_INTERNET) return;
+
handleLinkProp(network, newLp);
// Any non-LISTEN_ALL callback will necessarily concern a network that will
// also match the LISTEN_ALL callback by construction of the LISTEN_ALL callback.
@@ -409,17 +408,25 @@
@Override
public void onNetworkSuspended(Network network) {
- handleSuspended(mCallbackType, network);
+ if (mCallbackType == CALLBACK_LISTEN_ALL) {
+ handleSuspended(network);
+ }
}
@Override
public void onNetworkResumed(Network network) {
- handleResumed(mCallbackType, network);
+ if (mCallbackType == CALLBACK_LISTEN_ALL) {
+ handleResumed(network);
+ }
}
@Override
public void onLost(Network network) {
- handleLost(mCallbackType, network);
+ if (mCallbackType == CALLBACK_DEFAULT_INTERNET) {
+ mDefaultInternetNetwork = null;
+ return;
+ }
+ handleLost(network);
// Any non-LISTEN_ALL callback will necessarily concern a network that will
// also match the LISTEN_ALL callback by construction of the LISTEN_ALL callback.
// So it's not useful to do this work for non-LISTEN_ALL callbacks.
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index b9cc372..f037905 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -139,7 +139,8 @@
DROPPED_IPV6_MULTICAST_PING,
DROPPED_IPV6_NON_ICMP_MULTICAST,
DROPPED_802_3_FRAME,
- DROPPED_ETHERTYPE_BLACKLISTED;
+ DROPPED_ETHERTYPE_BLACKLISTED,
+ DROPPED_ARP_REPLY_SPA_NO_HOST;
// Returns the negative byte offset from the end of the APF data segment for
// a given counter.
@@ -156,7 +157,7 @@
/**
* When APFv4 is supported, loads R1 with the offset of the specified counter.
*/
- private void maybeSetCounter(ApfGenerator gen, Counter c) {
+ private void maybeSetupCounter(ApfGenerator gen, Counter c) {
if (mApfCapabilities.hasDataAccess()) {
gen.addLoadImmediate(Register.R1, c.offset());
}
@@ -288,16 +289,18 @@
private static final int DHCP_CLIENT_MAC_OFFSET = ETH_HEADER_LEN + UDP_HEADER_LEN + 28;
private static final int ARP_HEADER_OFFSET = ETH_HEADER_LEN;
- private static final int ARP_OPCODE_OFFSET = ARP_HEADER_OFFSET + 6;
- private static final short ARP_OPCODE_REQUEST = 1;
- private static final short ARP_OPCODE_REPLY = 2;
private static final byte[] ARP_IPV4_HEADER = {
0, 1, // Hardware type: Ethernet (1)
8, 0, // Protocol type: IP (0x0800)
6, // Hardware size: 6
4, // Protocol size: 4
};
- private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24;
+ private static final int ARP_OPCODE_OFFSET = ARP_HEADER_OFFSET + 6;
+ // Opcode: ARP request (0x0001), ARP reply (0x0002)
+ private static final short ARP_OPCODE_REQUEST = 1;
+ private static final short ARP_OPCODE_REPLY = 2;
+ private static final int ARP_SOURCE_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 14;
+ private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 24;
// Do not log ApfProgramEvents whose actual lifetimes was less than this.
private static final int APF_PROGRAM_EVENT_LIFETIME_THRESHOLD = 2;
// Limit on the Black List size to cap on program usage for this
@@ -816,7 +819,7 @@
gen.addJumpIfR0LessThan(filterLifetime, nextFilterLabel);
}
}
- maybeSetCounter(gen, Counter.DROPPED_RA);
+ maybeSetupCounter(gen, Counter.DROPPED_RA);
gen.addJump(mCountAndDropLabel);
gen.defineLabel(nextFilterLabel);
return filterLifetime;
@@ -883,6 +886,8 @@
// pass
// if not ARP IPv4 reply or request
// pass
+ // if ARP reply source ip is 0.0.0.0
+ // drop
// if unicast ARP reply
// pass
// if interface has no IPv4 address
@@ -897,18 +902,23 @@
// Pass if not ARP IPv4.
gen.addLoadImmediate(Register.R0, ARP_HEADER_OFFSET);
- maybeSetCounter(gen, Counter.PASSED_ARP_NON_IPV4);
+ maybeSetupCounter(gen, Counter.PASSED_ARP_NON_IPV4);
gen.addJumpIfBytesNotEqual(Register.R0, ARP_IPV4_HEADER, mCountAndPassLabel);
// Pass if unknown ARP opcode.
gen.addLoad16(Register.R0, ARP_OPCODE_OFFSET);
gen.addJumpIfR0Equals(ARP_OPCODE_REQUEST, checkTargetIPv4); // Skip to unicast check
- maybeSetCounter(gen, Counter.PASSED_ARP_UNKNOWN);
+ maybeSetupCounter(gen, Counter.PASSED_ARP_UNKNOWN);
gen.addJumpIfR0NotEquals(ARP_OPCODE_REPLY, mCountAndPassLabel);
+ // Drop if ARP reply source IP is 0.0.0.0
+ gen.addLoad32(Register.R0, ARP_SOURCE_IP_ADDRESS_OFFSET);
+ maybeSetupCounter(gen, Counter.DROPPED_ARP_REPLY_SPA_NO_HOST);
+ gen.addJumpIfR0Equals(IPV4_ANY_HOST_ADDRESS, mCountAndDropLabel);
+
// Pass if unicast reply.
gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
- maybeSetCounter(gen, Counter.PASSED_ARP_UNICAST_REPLY);
+ maybeSetupCounter(gen, Counter.PASSED_ARP_UNICAST_REPLY);
gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, mCountAndPassLabel);
// Either a unicast request, a unicast reply, or a broadcast reply.
@@ -916,17 +926,17 @@
if (mIPv4Address == null) {
// When there is no IPv4 address, drop GARP replies (b/29404209).
gen.addLoad32(Register.R0, ARP_TARGET_IP_ADDRESS_OFFSET);
- maybeSetCounter(gen, Counter.DROPPED_GARP_REPLY);
+ maybeSetupCounter(gen, Counter.DROPPED_GARP_REPLY);
gen.addJumpIfR0Equals(IPV4_ANY_HOST_ADDRESS, mCountAndDropLabel);
} else {
// When there is an IPv4 address, drop unicast/broadcast requests
// and broadcast replies with a different target IPv4 address.
gen.addLoadImmediate(Register.R0, ARP_TARGET_IP_ADDRESS_OFFSET);
- maybeSetCounter(gen, Counter.DROPPED_ARP_OTHER_HOST);
+ maybeSetupCounter(gen, Counter.DROPPED_ARP_OTHER_HOST);
gen.addJumpIfBytesNotEqual(Register.R0, mIPv4Address, mCountAndDropLabel);
}
- maybeSetCounter(gen, Counter.PASSED_ARP);
+ maybeSetupCounter(gen, Counter.PASSED_ARP);
gen.addJump(mCountAndPassLabel);
}
@@ -970,7 +980,7 @@
// NOTE: Relies on R1 containing IPv4 header offset.
gen.addAddR1();
gen.addJumpIfBytesNotEqual(Register.R0, mHardwareAddress, skipDhcpv4Filter);
- maybeSetCounter(gen, Counter.PASSED_DHCP);
+ maybeSetupCounter(gen, Counter.PASSED_DHCP);
gen.addJump(mCountAndPassLabel);
// Drop all multicasts/broadcasts.
@@ -979,30 +989,30 @@
// If IPv4 destination address is in multicast range, drop.
gen.addLoad8(Register.R0, IPV4_DEST_ADDR_OFFSET);
gen.addAnd(0xf0);
- maybeSetCounter(gen, Counter.DROPPED_IPV4_MULTICAST);
+ maybeSetupCounter(gen, Counter.DROPPED_IPV4_MULTICAST);
gen.addJumpIfR0Equals(0xe0, mCountAndDropLabel);
// If IPv4 broadcast packet, drop regardless of L2 (b/30231088).
- maybeSetCounter(gen, Counter.DROPPED_IPV4_BROADCAST_ADDR);
+ maybeSetupCounter(gen, Counter.DROPPED_IPV4_BROADCAST_ADDR);
gen.addLoad32(Register.R0, IPV4_DEST_ADDR_OFFSET);
gen.addJumpIfR0Equals(IPV4_BROADCAST_ADDRESS, mCountAndDropLabel);
if (mIPv4Address != null && mIPv4PrefixLength < 31) {
- maybeSetCounter(gen, Counter.DROPPED_IPV4_BROADCAST_NET);
+ maybeSetupCounter(gen, Counter.DROPPED_IPV4_BROADCAST_NET);
int broadcastAddr = ipv4BroadcastAddress(mIPv4Address, mIPv4PrefixLength);
gen.addJumpIfR0Equals(broadcastAddr, mCountAndDropLabel);
}
// If L2 broadcast packet, drop.
// TODO: can we invert this condition to fall through to the common pass case below?
- maybeSetCounter(gen, Counter.PASSED_IPV4_UNICAST);
+ maybeSetupCounter(gen, Counter.PASSED_IPV4_UNICAST);
gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, mCountAndPassLabel);
- maybeSetCounter(gen, Counter.DROPPED_IPV4_L2_BROADCAST);
+ maybeSetupCounter(gen, Counter.DROPPED_IPV4_L2_BROADCAST);
gen.addJump(mCountAndDropLabel);
}
// Otherwise, pass
- maybeSetCounter(gen, Counter.PASSED_IPV4);
+ maybeSetupCounter(gen, Counter.PASSED_IPV4);
gen.addJump(mCountAndPassLabel);
}
@@ -1050,16 +1060,16 @@
// Drop all other packets sent to ff00::/8 (multicast prefix).
gen.defineLabel(dropAllIPv6MulticastsLabel);
- maybeSetCounter(gen, Counter.DROPPED_IPV6_NON_ICMP_MULTICAST);
+ maybeSetupCounter(gen, Counter.DROPPED_IPV6_NON_ICMP_MULTICAST);
gen.addLoad8(Register.R0, IPV6_DEST_ADDR_OFFSET);
gen.addJumpIfR0Equals(0xff, mCountAndDropLabel);
// Not multicast. Pass.
- maybeSetCounter(gen, Counter.PASSED_IPV6_UNICAST_NON_ICMP);
+ maybeSetupCounter(gen, Counter.PASSED_IPV6_UNICAST_NON_ICMP);
gen.addJump(mCountAndPassLabel);
gen.defineLabel(skipIPv6MulticastFilterLabel);
} else {
// If not ICMPv6, pass.
- maybeSetCounter(gen, Counter.PASSED_IPV6_NON_ICMP);
+ maybeSetupCounter(gen, Counter.PASSED_IPV6_NON_ICMP);
gen.addJumpIfR0NotEquals(IPPROTO_ICMPV6, mCountAndPassLabel);
}
@@ -1069,7 +1079,7 @@
String skipUnsolicitedMulticastNALabel = "skipUnsolicitedMulticastNA";
gen.addLoad8(Register.R0, ICMP6_TYPE_OFFSET);
// Drop all router solicitations (b/32833400)
- maybeSetCounter(gen, Counter.DROPPED_IPV6_ROUTER_SOLICITATION);
+ maybeSetupCounter(gen, Counter.DROPPED_IPV6_ROUTER_SOLICITATION);
gen.addJumpIfR0Equals(ICMPV6_ROUTER_SOLICITATION, mCountAndDropLabel);
// If not neighbor announcements, skip filter.
gen.addJumpIfR0NotEquals(ICMPV6_NEIGHBOR_ADVERTISEMENT, skipUnsolicitedMulticastNALabel);
@@ -1078,7 +1088,7 @@
gen.addLoadImmediate(Register.R0, IPV6_DEST_ADDR_OFFSET);
gen.addJumpIfBytesNotEqual(Register.R0, IPV6_ALL_NODES_ADDRESS,
skipUnsolicitedMulticastNALabel);
- maybeSetCounter(gen, Counter.DROPPED_IPV6_MULTICAST_NA);
+ maybeSetupCounter(gen, Counter.DROPPED_IPV6_MULTICAST_NA);
gen.addJump(mCountAndDropLabel);
gen.defineLabel(skipUnsolicitedMulticastNALabel);
}
@@ -1108,7 +1118,7 @@
if (mApfCapabilities.hasDataAccess()) {
// Increment TOTAL_PACKETS
- maybeSetCounter(gen, Counter.TOTAL_PACKETS);
+ maybeSetupCounter(gen, Counter.TOTAL_PACKETS);
gen.addLoadData(Register.R0, 0); // load counter
gen.addAdd(1);
gen.addStoreData(Register.R0, 0); // write-back counter
@@ -1134,12 +1144,12 @@
if (mDrop802_3Frames) {
// drop 802.3 frames (ethtype < 0x0600)
- maybeSetCounter(gen, Counter.DROPPED_802_3_FRAME);
+ maybeSetupCounter(gen, Counter.DROPPED_802_3_FRAME);
gen.addJumpIfR0LessThan(ETH_TYPE_MIN, mCountAndDropLabel);
}
// Handle ether-type black list
- maybeSetCounter(gen, Counter.DROPPED_ETHERTYPE_BLACKLISTED);
+ maybeSetupCounter(gen, Counter.DROPPED_ETHERTYPE_BLACKLISTED);
for (int p : mEthTypeBlackList) {
gen.addJumpIfR0Equals(p, mCountAndDropLabel);
}
@@ -1168,9 +1178,9 @@
// Drop non-IP non-ARP broadcasts, pass the rest
gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
- maybeSetCounter(gen, Counter.PASSED_NON_IP_UNICAST);
+ maybeSetupCounter(gen, Counter.PASSED_NON_IP_UNICAST);
gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, mCountAndPassLabel);
- maybeSetCounter(gen, Counter.DROPPED_ETH_BROADCAST);
+ maybeSetupCounter(gen, Counter.DROPPED_ETH_BROADCAST);
gen.addJump(mCountAndDropLabel);
// Add IPv6 filters:
@@ -1193,7 +1203,7 @@
// Execution will reach the bottom of the program if none of the filters match,
// which will pass the packet to the application processor.
- maybeSetCounter(gen, Counter.PASSED_IPV6_ICMP);
+ maybeSetupCounter(gen, Counter.PASSED_IPV6_ICMP);
// Append the count & pass trampoline, which increments the counter at the data address
// pointed to by R1, then jumps to the pass label. This saves a few bytes over inserting
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index af8596d..d2d6e32 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -67,7 +67,7 @@
"liblzma",
"libnativehelper",
"libui",
- "libunwind",
+ "libunwindstack",
"libutils",
"netd_aidl_interface-cpp",
],
diff --git a/startop/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc
index 906d64c..94879d0 100644
--- a/startop/view_compiler/dex_builder.cc
+++ b/startop/view_compiler/dex_builder.cc
@@ -61,18 +61,46 @@
case Instruction::Op::kInvokeDirect:
out << "kInvokeDirect";
return out;
+ case Instruction::Op::kInvokeStatic:
+ out << "kInvokeStatic";
+ return out;
+ case Instruction::Op::kInvokeInterface:
+ out << "kInvokeInterface";
+ return out;
case Instruction::Op::kBindLabel:
out << "kBindLabel";
return out;
case Instruction::Op::kBranchEqz:
out << "kBranchEqz";
return out;
+ case Instruction::Op::kBranchNEqz:
+ out << "kBranchNEqz";
+ return out;
case Instruction::Op::kNew:
out << "kNew";
return out;
}
}
+std::ostream& operator<<(std::ostream& out, const Value& value) {
+ if (value.is_register()) {
+ out << "Register(" << value.value() << ")";
+ } else if (value.is_parameter()) {
+ out << "Parameter(" << value.value() << ")";
+ } else if (value.is_immediate()) {
+ out << "Immediate(" << value.value() << ")";
+ } else if (value.is_string()) {
+ out << "String(" << value.value() << ")";
+ } else if (value.is_label()) {
+ out << "Label(" << value.value() << ")";
+ } else if (value.is_type()) {
+ out << "Type(" << value.value() << ")";
+ } else {
+ out << "UnknownValue";
+ }
+ return out;
+}
+
void* TrackingAllocator::Allocate(size_t size) {
std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(size);
void* raw_buffer = buffer.get();
@@ -289,10 +317,16 @@
return EncodeInvoke(instruction, art::Instruction::INVOKE_VIRTUAL);
case Instruction::Op::kInvokeDirect:
return EncodeInvoke(instruction, art::Instruction::INVOKE_DIRECT);
+ case Instruction::Op::kInvokeStatic:
+ return EncodeInvoke(instruction, art::Instruction::INVOKE_STATIC);
+ case Instruction::Op::kInvokeInterface:
+ return EncodeInvoke(instruction, art::Instruction::INVOKE_INTERFACE);
case Instruction::Op::kBindLabel:
return BindLabel(instruction.args()[0]);
case Instruction::Op::kBranchEqz:
return EncodeBranch(art::Instruction::IF_EQZ, instruction);
+ case Instruction::Op::kBranchNEqz:
+ return EncodeBranch(art::Instruction::IF_NEZ, instruction);
case Instruction::Op::kNew:
return EncodeNew(instruction);
}
@@ -353,7 +387,9 @@
// If there is a return value, add a move-result instruction
if (instruction.dest().has_value()) {
- Encode11x(art::Instruction::MOVE_RESULT, RegisterValue(*instruction.dest()));
+ Encode11x(instruction.result_is_object() ? art::Instruction::MOVE_RESULT_OBJECT
+ : art::Instruction::MOVE_RESULT,
+ RegisterValue(*instruction.dest()));
}
max_args_ = std::max(max_args_, instruction.args().size());
@@ -447,7 +483,7 @@
auto& ir_node = dex_file_->methods_map[new_index];
SLICER_CHECK(ir_node == nullptr);
ir_node = decl;
- decl->orig_index = new_index;
+ decl->orig_index = decl->index = new_index;
entry = {id, decl};
}
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h
index adf82bf..45596ac 100644
--- a/startop/view_compiler/dex_builder.h
+++ b/startop/view_compiler/dex_builder.h
@@ -147,8 +147,11 @@
kMove,
kInvokeVirtual,
kInvokeDirect,
+ kInvokeStatic,
+ kInvokeInterface,
kBindLabel,
kBranchEqz,
+ kBranchNEqz,
kNew
};
@@ -163,19 +166,53 @@
// For most instructions, which take some number of arguments and have an optional return value.
template <typename... T>
static inline Instruction OpWithArgs(Op opcode, std::optional<const Value> dest, T... args) {
- return Instruction{opcode, /*method_id*/ 0, dest, args...};
+ return Instruction{opcode, /*method_id=*/0, /*result_is_object=*/false, dest, args...};
}
// For method calls.
template <typename... T>
static inline Instruction InvokeVirtual(size_t method_id, std::optional<const Value> dest,
Value this_arg, T... args) {
- return Instruction{Op::kInvokeVirtual, method_id, dest, this_arg, args...};
+ return Instruction{
+ Op::kInvokeVirtual, method_id, /*result_is_object=*/false, dest, this_arg, args...};
+ }
+ // Returns an object
+ template <typename... T>
+ static inline Instruction InvokeVirtualObject(size_t method_id, std::optional<const Value> dest,
+ Value this_arg, T... args) {
+ return Instruction{
+ Op::kInvokeVirtual, method_id, /*result_is_object=*/true, dest, this_arg, args...};
}
// For direct calls (basically, constructors).
template <typename... T>
static inline Instruction InvokeDirect(size_t method_id, std::optional<const Value> dest,
Value this_arg, T... args) {
- return Instruction{Op::kInvokeDirect, method_id, dest, this_arg, args...};
+ return Instruction{
+ Op::kInvokeDirect, method_id, /*result_is_object=*/false, dest, this_arg, args...};
+ }
+ // Returns an object
+ template <typename... T>
+ static inline Instruction InvokeDirectObject(size_t method_id, std::optional<const Value> dest,
+ Value this_arg, T... args) {
+ return Instruction{
+ Op::kInvokeDirect, method_id, /*result_is_object=*/true, dest, this_arg, args...};
+ }
+ // For static calls.
+ template <typename... T>
+ static inline Instruction InvokeStatic(size_t method_id, std::optional<const Value> dest,
+ T... args) {
+ return Instruction{Op::kInvokeStatic, method_id, /*result_is_object=*/false, dest, args...};
+ }
+ // Returns an object
+ template <typename... T>
+ static inline Instruction InvokeStaticObject(size_t method_id, std::optional<const Value> dest,
+ T... args) {
+ return Instruction{Op::kInvokeStatic, method_id, /*result_is_object=*/true, dest, args...};
+ }
+ // For static calls.
+ template <typename... T>
+ static inline Instruction InvokeInterface(size_t method_id, std::optional<const Value> dest,
+ T... args) {
+ return Instruction{Op::kInvokeInterface, method_id, /*result_is_object=*/false, dest, args...};
}
///////////////
@@ -184,21 +221,27 @@
Op opcode() const { return opcode_; }
size_t method_id() const { return method_id_; }
+ bool result_is_object() const { return result_is_object_; }
const std::optional<const Value>& dest() const { return dest_; }
const std::vector<const Value>& args() const { return args_; }
private:
inline Instruction(Op opcode, size_t method_id, std::optional<const Value> dest)
- : opcode_{opcode}, method_id_{method_id}, dest_{dest}, args_{} {}
+ : opcode_{opcode}, method_id_{method_id}, result_is_object_{false}, dest_{dest}, args_{} {}
template <typename... T>
- inline constexpr Instruction(Op opcode, size_t method_id, std::optional<const Value> dest,
- T... args)
- : opcode_{opcode}, method_id_{method_id}, dest_{dest}, args_{args...} {}
+ inline constexpr Instruction(Op opcode, size_t method_id, bool result_is_object,
+ std::optional<const Value> dest, T... args)
+ : opcode_{opcode},
+ method_id_{method_id},
+ result_is_object_{result_is_object},
+ dest_{dest},
+ args_{args...} {}
const Op opcode_;
// The index of the method to invoke, for kInvokeVirtual and similar opcodes.
const size_t method_id_{0};
+ const bool result_is_object_;
const std::optional<const Value> dest_;
const std::vector<const Value> args_;
};
@@ -244,6 +287,8 @@
// TODO: add builders for more instructions
+ DexBuilder* dex_file() const { return dex_; }
+
private:
void EncodeInstructions();
void EncodeInstruction(const Instruction& instruction);
diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
index e20f3a9..1508ad9e 100644
--- a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
+++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
@@ -84,6 +84,15 @@
}
@Test
+ public void returnIfNotZero() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("returnIfNotZero", int.class);
+ Assert.assertEquals(3, method.invoke(null, 0));
+ Assert.assertEquals(5, method.invoke(null, 17));
+ }
+
+ @Test
public void backwardsBranch() throws Exception {
ClassLoader loader = loadDexFile("simple.dex");
Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
@@ -124,4 +133,22 @@
Assert.assertEquals("b", method.invoke(null, 0));
Assert.assertEquals("a", method.invoke(null, 1));
}
+
+ @Test
+ public void invokeStaticReturnObject() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("invokeStaticReturnObject", int.class, int.class);
+ Assert.assertEquals("10", method.invoke(null, 10, 10));
+ Assert.assertEquals("a", method.invoke(null, 10, 16));
+ Assert.assertEquals("5", method.invoke(null, 5, 16));
+ }
+
+ @Test
+ public void invokeVirtualReturnObject() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("invokeVirtualReturnObject", String.class, int.class);
+ Assert.assertEquals("bc", method.invoke(null, "abc", 1));
+ }
}
diff --git a/startop/view_compiler/dex_testcase_generator.cc b/startop/view_compiler/dex_testcase_generator.cc
index e2bf43bc..2781aa5 100644
--- a/startop/view_compiler/dex_testcase_generator.cc
+++ b/startop/view_compiler/dex_testcase_generator.cc
@@ -108,6 +108,27 @@
}
returnIfZero.Encode();
+ // int returnIfNotZero(int x) { if (x != 0) { return 5; } else { return 3; } }
+ MethodBuilder returnIfNotZero{cbuilder.CreateMethod(
+ "returnIfNotZero", Prototype{TypeDescriptor::Int(), TypeDescriptor::Int()})};
+ {
+ Value resultIfNotZero{returnIfNotZero.MakeRegister()};
+ Value else_target{returnIfNotZero.MakeLabel()};
+ returnIfNotZero.AddInstruction(Instruction::OpWithArgs(
+ Instruction::Op::kBranchNEqz, /*dest=*/{}, Value::Parameter(0), else_target));
+ // else branch
+ returnIfNotZero.BuildConst4(resultIfNotZero, 3);
+ returnIfNotZero.AddInstruction(
+ Instruction::OpWithArgs(Instruction::Op::kReturn, /*dest=*/{}, resultIfNotZero));
+ // then branch
+ returnIfNotZero.AddInstruction(
+ Instruction::OpWithArgs(Instruction::Op::kBindLabel, /*dest=*/{}, else_target));
+ returnIfNotZero.BuildConst4(resultIfNotZero, 5);
+ returnIfNotZero.AddInstruction(
+ Instruction::OpWithArgs(Instruction::Op::kReturn, /*dest=*/{}, resultIfNotZero));
+ }
+ returnIfNotZero.Encode();
+
// Make sure backwards branches work too.
//
// Pseudo code for test:
@@ -216,6 +237,38 @@
method.Encode();
}(returnStringIfZeroBA);
+ // Make sure we can invoke static methods that return an object
+ // String invokeStaticReturnObject(int n, int radix) { return java.lang.Integer.toString(n,
+ // radix); }
+ MethodBuilder invokeStaticReturnObject{
+ cbuilder.CreateMethod("invokeStaticReturnObject",
+ Prototype{string_type, TypeDescriptor::Int(), TypeDescriptor::Int()})};
+ [&](MethodBuilder& method) {
+ Value result{method.MakeRegister()};
+ MethodDeclData to_string{dex_file.GetOrDeclareMethod(
+ TypeDescriptor::FromClassname("java.lang.Integer"),
+ "toString",
+ Prototype{string_type, TypeDescriptor::Int(), TypeDescriptor::Int()})};
+ method.AddInstruction(Instruction::InvokeStaticObject(
+ to_string.id, result, Value::Parameter(0), Value::Parameter(1)));
+ method.BuildReturn(result, /*is_object=*/true);
+ method.Encode();
+ }(invokeStaticReturnObject);
+
+ // Make sure we can invoke virtual methods that return an object
+ // String invokeVirtualReturnObject(String s, int n) { return s.substring(n); }
+ MethodBuilder invokeVirtualReturnObject{cbuilder.CreateMethod(
+ "invokeVirtualReturnObject", Prototype{string_type, string_type, TypeDescriptor::Int()})};
+ [&](MethodBuilder& method) {
+ Value result{method.MakeRegister()};
+ MethodDeclData substring{dex_file.GetOrDeclareMethod(
+ string_type, "substring", Prototype{string_type, TypeDescriptor::Int()})};
+ method.AddInstruction(Instruction::InvokeVirtualObject(
+ substring.id, result, Value::Parameter(0), Value::Parameter(1)));
+ method.BuildReturn(result, /*is_object=*/true);
+ method.Encode();
+ }(invokeVirtualReturnObject);
+
slicer::MemView image{dex_file.CreateImage()};
std::ofstream out_file(outdir + "/simple.dex");
out_file.write(image.ptr<const char>(), image.size());
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index bf0ffb9..36d0188 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -29,7 +29,6 @@
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
-import java.lang.String;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
@@ -919,10 +918,16 @@
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append("[pa: ");
+ sb.append("[id: ");
+ sb.append(mTelecomCallId);
+ sb.append(", pa: ");
sb.append(mAccountHandle);
sb.append(", hdl: ");
- sb.append(Log.pii(mHandle));
+ sb.append(Log.piiHandle(mHandle));
+ sb.append(", hdlPres: ");
+ sb.append(mHandlePresentation);
+ sb.append(", videoState: ");
+ sb.append(VideoProfile.videoStateToString(mVideoState));
sb.append(", caps: ");
sb.append(capabilitiesToString(mCallCapabilities));
sb.append(", props: ");
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
index 7db6940..6628743 100644
--- a/telecomm/java/android/telecom/CallScreeningService.java
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -27,8 +27,8 @@
import android.os.RemoteException;
import com.android.internal.os.SomeArgs;
-import com.android.internal.telecom.ICallScreeningService;
import com.android.internal.telecom.ICallScreeningAdapter;
+import com.android.internal.telecom.ICallScreeningService;
/**
* This service can be implemented by the default dialer (see
@@ -147,7 +147,7 @@
private boolean mShouldSkipCallLog;
private boolean mShouldSkipNotification;
- /*
+ /**
* Sets whether the incoming call should be blocked.
*/
public Builder setDisallowCall(boolean shouldDisallowCall) {
@@ -155,7 +155,7 @@
return this;
}
- /*
+ /**
* Sets whether the incoming call should be disconnected as if the user had manually
* rejected it. This property should only be set to true if the call is disallowed.
*/
@@ -164,16 +164,20 @@
return this;
}
- /*
+ /**
* Sets whether the incoming call should not be displayed in the call log. This property
* should only be set to true if the call is disallowed.
+ * <p>
+ * Note: Calls will still be logged with type
+ * {@link android.provider.CallLog.Calls#BLOCKED_TYPE}, regardless of how this property
+ * is set.
*/
public Builder setSkipCallLog(boolean shouldSkipCallLog) {
mShouldSkipCallLog = shouldSkipCallLog;
return this;
}
- /*
+ /**
* Sets whether a missed call notification should not be shown for the incoming call.
* This property should only be set to true if the call is disallowed.
*/
@@ -211,6 +215,17 @@
* Called when a new incoming call is added.
* {@link CallScreeningService#respondToCall(Call.Details, CallScreeningService.CallResponse)}
* should be called to allow or disallow the call.
+ * <p>
+ * Note: The {@link Call.Details} instance provided to a call screening service will only have
+ * the following properties set. The rest of the {@link Call.Details} properties will be set to
+ * their default value or {@code null}.
+ * <ul>
+ * <li>{@link Call.Details#getState()}</li>
+ * <li>{@link Call.Details#getConnectTimeMillis()}</li>
+ * <li>{@link Call.Details#getCreationTimeMillis()}</li>
+ * <li>{@link Call.Details#getHandle()}</li>
+ * <li>{@link Call.Details#getHandlePresentation()}</li>
+ * </ul>
*
* @param callDetails Information about a new incoming call, see {@link Call.Details}.
*/
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 14e0909..fed58c1 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1392,9 +1392,9 @@
* Example: "default"
*
* {@code ERROR_CODE_1} is an integer defined in
- * {@link com.android.internal.telephony.dataconnection.DcFailCause DcFailure}
+ * {@link DataFailCause DcFailure}
* Example:
- * {@link com.android.internal.telephony.dataconnection.DcFailCause#MISSING_UNKNOWN_APN}
+ * {@link DataFailCause#MISSING_UNKNOWN_APN}
*
* {@code CARRIER_ACTION_IDX_1} is an integer defined in
* {@link com.android.carrierdefaultapp.CarrierActionUtils CarrierActionUtils}
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
new file mode 100644
index 0000000..c6f7d0e
--- /dev/null
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.telephony;
+
+import android.content.Context;
+import android.os.PersistableBundle;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+
+/**
+ * Returned as the reason for a connection failure as defined
+ * by RIL_DataCallFailCause in ril.h and some local errors.
+ * @hide
+ */
+public enum DataFailCause {
+ NONE(0),
+
+ // This series of errors as specified by the standards
+ // specified in ril.h
+ OPERATOR_BARRED(0x08), /* no retry */
+ NAS_SIGNALLING(0x0E),
+ LLC_SNDCP(0x19),
+ INSUFFICIENT_RESOURCES(0x1A),
+ MISSING_UNKNOWN_APN(0x1B), /* no retry */
+ UNKNOWN_PDP_ADDRESS_TYPE(0x1C), /* no retry */
+ USER_AUTHENTICATION(0x1D), /* no retry */
+ ACTIVATION_REJECT_GGSN(0x1E), /* no retry */
+ ACTIVATION_REJECT_UNSPECIFIED(0x1F),
+ SERVICE_OPTION_NOT_SUPPORTED(0x20), /* no retry */
+ SERVICE_OPTION_NOT_SUBSCRIBED(0x21), /* no retry */
+ SERVICE_OPTION_OUT_OF_ORDER(0x22),
+ NSAPI_IN_USE(0x23), /* no retry */
+ REGULAR_DEACTIVATION(0x24), /* possibly restart radio, based on config */
+ QOS_NOT_ACCEPTED(0x25),
+ NETWORK_FAILURE(0x26),
+ UMTS_REACTIVATION_REQ(0x27),
+ FEATURE_NOT_SUPP(0x28),
+ TFT_SEMANTIC_ERROR(0x29),
+ TFT_SYTAX_ERROR(0x2A),
+ UNKNOWN_PDP_CONTEXT(0x2B),
+ FILTER_SEMANTIC_ERROR(0x2C),
+ FILTER_SYTAX_ERROR(0x2D),
+ PDP_WITHOUT_ACTIVE_TFT(0x2E),
+ ONLY_IPV4_ALLOWED(0x32), /* no retry */
+ ONLY_IPV6_ALLOWED(0x33), /* no retry */
+ ONLY_SINGLE_BEARER_ALLOWED(0x34),
+ ESM_INFO_NOT_RECEIVED(0x35),
+ PDN_CONN_DOES_NOT_EXIST(0x36),
+ MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED(0x37),
+ MAX_ACTIVE_PDP_CONTEXT_REACHED(0x41),
+ UNSUPPORTED_APN_IN_CURRENT_PLMN(0x42),
+ INVALID_TRANSACTION_ID(0x51),
+ MESSAGE_INCORRECT_SEMANTIC(0x5F),
+ INVALID_MANDATORY_INFO(0x60),
+ MESSAGE_TYPE_UNSUPPORTED(0x61),
+ MSG_TYPE_NONCOMPATIBLE_STATE(0x62),
+ UNKNOWN_INFO_ELEMENT(0x63),
+ CONDITIONAL_IE_ERROR(0x64),
+ MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE(0x65),
+ PROTOCOL_ERRORS(0x6F), /* no retry */
+ APN_TYPE_CONFLICT(0x70),
+ INVALID_PCSCF_ADDR(0x71),
+ INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN(0x72),
+ EMM_ACCESS_BARRED(0x73),
+ EMERGENCY_IFACE_ONLY(0x74),
+ IFACE_MISMATCH(0x75),
+ COMPANION_IFACE_IN_USE(0x76),
+ IP_ADDRESS_MISMATCH(0x77),
+ IFACE_AND_POL_FAMILY_MISMATCH(0x78),
+ EMM_ACCESS_BARRED_INFINITE_RETRY(0x79),
+ AUTH_FAILURE_ON_EMERGENCY_CALL(0x7A),
+
+ // OEM sepecific error codes. To be used by OEMs when they don't
+ // want to reveal error code which would be replaced by ERROR_UNSPECIFIED
+ OEM_DCFAILCAUSE_1(0x1001),
+ OEM_DCFAILCAUSE_2(0x1002),
+ OEM_DCFAILCAUSE_3(0x1003),
+ OEM_DCFAILCAUSE_4(0x1004),
+ OEM_DCFAILCAUSE_5(0x1005),
+ OEM_DCFAILCAUSE_6(0x1006),
+ OEM_DCFAILCAUSE_7(0x1007),
+ OEM_DCFAILCAUSE_8(0x1008),
+ OEM_DCFAILCAUSE_9(0x1009),
+ OEM_DCFAILCAUSE_10(0x100A),
+ OEM_DCFAILCAUSE_11(0x100B),
+ OEM_DCFAILCAUSE_12(0x100C),
+ OEM_DCFAILCAUSE_13(0x100D),
+ OEM_DCFAILCAUSE_14(0x100E),
+ OEM_DCFAILCAUSE_15(0x100F),
+
+ // Local errors generated by Vendor RIL
+ // specified in ril.h
+ REGISTRATION_FAIL(-1),
+ GPRS_REGISTRATION_FAIL(-2),
+ SIGNAL_LOST(-3), /* no retry */
+ PREF_RADIO_TECH_CHANGED(-4),
+ RADIO_POWER_OFF(-5), /* no retry */
+ TETHERED_CALL_ACTIVE(-6), /* no retry */
+ ERROR_UNSPECIFIED(0xFFFF),
+
+ // Errors generated by the Framework
+ // specified here
+ UNKNOWN(0x10000),
+ RADIO_NOT_AVAILABLE(0x10001), /* no retry */
+ UNACCEPTABLE_NETWORK_PARAMETER(0x10002), /* no retry */
+ CONNECTION_TO_DATACONNECTIONAC_BROKEN(0x10003),
+ LOST_CONNECTION(0x10004),
+ RESET_BY_FRAMEWORK(0x10005);
+
+ private final int mErrorCode;
+ private static final HashMap<Integer, DataFailCause> sErrorCodeToFailCauseMap;
+ static {
+ sErrorCodeToFailCauseMap = new HashMap<Integer, DataFailCause>();
+ for (DataFailCause fc : values()) {
+ sErrorCodeToFailCauseMap.put(fc.getErrorCode(), fc);
+ }
+ }
+
+ /**
+ * Map of subId -> set of data call setup permanent failure for the carrier.
+ */
+ private static final HashMap<Integer, HashSet<DataFailCause>> sPermanentFailureCache =
+ new HashMap<>();
+
+ DataFailCause(int errorCode) {
+ mErrorCode = errorCode;
+ }
+
+ public int getErrorCode() {
+ return mErrorCode;
+ }
+
+ /**
+ * Returns whether or not the fail cause is a failure that requires a modem restart
+ *
+ * @param context device context
+ * @param subId subscription index
+ * @return true if the fail cause code needs platform to trigger a modem restart.
+ */
+ public boolean isRadioRestartFailure(Context context, int subId) {
+ CarrierConfigManager configManager = (CarrierConfigManager)
+ context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ if (configManager != null) {
+ PersistableBundle b = configManager.getConfigForSubId(subId);
+
+ if (b != null) {
+ if (this == REGULAR_DEACTIVATION
+ && b.getBoolean(CarrierConfigManager
+ .KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL)) {
+ // This is for backward compatibility support. We need to continue support this
+ // old configuration until it gets removed in the future.
+ return true;
+ }
+ // Check the current configurations.
+ int[] causeCodes = b.getIntArray(CarrierConfigManager
+ .KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY);
+ if (causeCodes != null) {
+ return Arrays.stream(causeCodes).anyMatch(i -> i == getErrorCode());
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public boolean isPermanentFailure(Context context, int subId) {
+
+ synchronized (sPermanentFailureCache) {
+
+ HashSet<DataFailCause> permanentFailureSet = sPermanentFailureCache.get(subId);
+
+ // In case of cache miss, we need to look up the settings from carrier config.
+ if (permanentFailureSet == null) {
+ // Retrieve the permanent failure from carrier config
+ CarrierConfigManager configManager = (CarrierConfigManager)
+ context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ if (configManager != null) {
+ PersistableBundle b = configManager.getConfigForSubId(subId);
+ if (b != null) {
+ String[] permanentFailureStrings = b.getStringArray(CarrierConfigManager.
+ KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS);
+
+ if (permanentFailureStrings != null) {
+ permanentFailureSet = new HashSet<>();
+ for (String failure : permanentFailureStrings) {
+ permanentFailureSet.add(DataFailCause.valueOf(failure));
+ }
+ }
+ }
+ }
+
+ // If we are not able to find the configuration from carrier config, use the default
+ // ones.
+ if (permanentFailureSet == null) {
+ permanentFailureSet = new HashSet<DataFailCause>() {
+ {
+ add(OPERATOR_BARRED);
+ add(MISSING_UNKNOWN_APN);
+ add(UNKNOWN_PDP_ADDRESS_TYPE);
+ add(USER_AUTHENTICATION);
+ add(ACTIVATION_REJECT_GGSN);
+ add(SERVICE_OPTION_NOT_SUPPORTED);
+ add(SERVICE_OPTION_NOT_SUBSCRIBED);
+ add(NSAPI_IN_USE);
+ add(ONLY_IPV4_ALLOWED);
+ add(ONLY_IPV6_ALLOWED);
+ add(PROTOCOL_ERRORS);
+ add(RADIO_POWER_OFF);
+ add(TETHERED_CALL_ACTIVE);
+ add(RADIO_NOT_AVAILABLE);
+ add(UNACCEPTABLE_NETWORK_PARAMETER);
+ add(SIGNAL_LOST);
+ }
+ };
+ }
+
+ sPermanentFailureCache.put(subId, permanentFailureSet);
+ }
+
+ return permanentFailureSet.contains(this);
+ }
+ }
+
+ public boolean isEventLoggable() {
+ return (this == OPERATOR_BARRED) || (this == INSUFFICIENT_RESOURCES) ||
+ (this == UNKNOWN_PDP_ADDRESS_TYPE) || (this == USER_AUTHENTICATION) ||
+ (this == ACTIVATION_REJECT_GGSN) || (this == ACTIVATION_REJECT_UNSPECIFIED) ||
+ (this == SERVICE_OPTION_NOT_SUBSCRIBED) ||
+ (this == SERVICE_OPTION_NOT_SUPPORTED) ||
+ (this == SERVICE_OPTION_OUT_OF_ORDER) || (this == NSAPI_IN_USE) ||
+ (this == ONLY_IPV4_ALLOWED) || (this == ONLY_IPV6_ALLOWED) ||
+ (this == PROTOCOL_ERRORS) || (this == SIGNAL_LOST) ||
+ (this == RADIO_POWER_OFF) || (this == TETHERED_CALL_ACTIVE) ||
+ (this == UNACCEPTABLE_NETWORK_PARAMETER);
+ }
+
+ public static DataFailCause fromInt(int errorCode) {
+ DataFailCause fc = sErrorCodeToFailCauseMap.get(errorCode);
+ if (fc == null) {
+ fc = UNKNOWN;
+ }
+ return fc;
+ }
+}
diff --git a/telephony/java/android/telephony/NetworkService.java b/telephony/java/android/telephony/NetworkService.java
index 4354314..4bca404 100644
--- a/telephony/java/android/telephony/NetworkService.java
+++ b/telephony/java/android/telephony/NetworkService.java
@@ -16,7 +16,6 @@
package android.telephony;
-import android.annotation.CallSuper;
import android.annotation.SystemApi;
import android.app.Service;
import android.content.Intent;
@@ -53,7 +52,6 @@
private final String TAG = NetworkService.class.getSimpleName();
public static final String NETWORK_SERVICE_INTERFACE = "android.telephony.NetworkService";
- public static final String NETWORK_SERVICE_EXTRA_SLOT_ID = "android.telephony.extra.SLOT_ID";
private static final int NETWORK_SERVICE_CREATE_NETWORK_SERVICE_PROVIDER = 1;
private static final int NETWORK_SERVICE_REMOVE_NETWORK_SERVICE_PROVIDER = 2;
@@ -81,7 +79,7 @@
* must extend this class to support network connection. Note that each instance of network
* service is associated with one physical SIM slot.
*/
- public class NetworkServiceProvider {
+ public abstract class NetworkServiceProvider implements AutoCloseable {
private final int mSlotId;
private final List<INetworkServiceCallback>
@@ -137,12 +135,12 @@
}
/**
- * Called when the instance of network service is destroyed (e.g. got unbind or binder died).
+ * Called when the instance of network service is destroyed (e.g. got unbind or binder died)
+ * or when the network service provider is removed. The extended class should implement this
+ * method to perform cleanup works.
*/
- @CallSuper
- protected void onDestroy() {
- mNetworkRegistrationStateChangedCallbacks.clear();
- }
+ @Override
+ public abstract void close();
}
private class NetworkServiceHandler extends Handler {
@@ -168,7 +166,7 @@
case NETWORK_SERVICE_REMOVE_NETWORK_SERVICE_PROVIDER:
// If the service provider doesn't exist yet, we try to create it.
if (serviceProvider != null) {
- serviceProvider.onDestroy();
+ serviceProvider.close();
mServiceMap.remove(slotId);
}
break;
@@ -176,7 +174,7 @@
for (int i = 0; i < mServiceMap.size(); i++) {
serviceProvider = mServiceMap.get(i);
if (serviceProvider != null) {
- serviceProvider.onDestroy();
+ serviceProvider.close();
}
}
mServiceMap.clear();
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index 1db5850..74d1e83 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -16,7 +16,6 @@
package android.telephony.data;
-import android.annotation.CallSuper;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -60,7 +59,6 @@
private static final String TAG = DataService.class.getSimpleName();
public static final String DATA_SERVICE_INTERFACE = "android.telephony.data.DataService";
- public static final String DATA_SERVICE_EXTRA_SLOT_ID = "android.telephony.data.extra.SLOT_ID";
/** {@hide} */
@IntDef(prefix = "REQUEST_REASON_", value = {
@@ -116,7 +114,7 @@
* must extend this class to support data connection. Note that each instance of data service
* provider is associated with one physical SIM slot.
*/
- public class DataServiceProvider {
+ public abstract class DataServiceProvider implements AutoCloseable {
private final int mSlotId;
@@ -250,12 +248,12 @@
}
/**
- * Called when the instance of data service is destroyed (e.g. got unbind or binder died).
+ * Called when the instance of data service is destroyed (e.g. got unbind or binder died)
+ * or when the data service provider is removed. The extended class should implement this
+ * method to perform cleanup works.
*/
- @CallSuper
- protected void onDestroy() {
- mDataCallListChangedCallbacks.clear();
- }
+ @Override
+ public abstract void close();
}
private static final class SetupDataCallRequest {
@@ -345,7 +343,7 @@
break;
case DATA_SERVICE_REMOVE_DATA_SERVICE_PROVIDER:
if (serviceProvider != null) {
- serviceProvider.onDestroy();
+ serviceProvider.close();
mServiceMap.remove(slotId);
}
break;
@@ -353,7 +351,7 @@
for (int i = 0; i < mServiceMap.size(); i++) {
serviceProvider = mServiceMap.get(i);
if (serviceProvider != null) {
- serviceProvider.onDestroy();
+ serviceProvider.close();
}
}
mServiceMap.clear();
diff --git a/telephony/java/android/telephony/data/QualifiedNetworksService.java b/telephony/java/android/telephony/data/QualifiedNetworksService.java
index 57d9cce..45b4849 100644
--- a/telephony/java/android/telephony/data/QualifiedNetworksService.java
+++ b/telephony/java/android/telephony/data/QualifiedNetworksService.java
@@ -151,7 +151,7 @@
/**
* Called when the qualified networks updater is removed. The extended class should
- * implement this method to perform clean up works.
+ * implement this method to perform cleanup works.
*/
@Override
public abstract void close();
diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
index f124595..4d95e55 100644
--- a/telephony/java/android/telephony/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -331,7 +331,80 @@
*/
public static final int CODE_SIP_USER_MARKED_UNWANTED = 365;
- /*
+ /**
+ * SIP Response : 405
+ * Method not allowed for the address in the Request URI
+ */
+ public static final int CODE_SIP_METHOD_NOT_ALLOWED = 366;
+
+ /**
+ * SIP Response : 407
+ * The request requires user authentication
+ */
+ public static final int CODE_SIP_PROXY_AUTHENTICATION_REQUIRED = 367;
+
+ /**
+ * SIP Response : 413
+ * Request body too large
+ */
+ public static final int CODE_SIP_REQUEST_ENTITY_TOO_LARGE = 368;
+
+ /**
+ * SIP Response : 414
+ * Request-URI too large
+ */
+ public static final int CODE_SIP_REQUEST_URI_TOO_LARGE = 369;
+
+ /**
+ * SIP Response : 421
+ * Specific extension is required, which is not present in the HEADER
+ */
+ public static final int CODE_SIP_EXTENSION_REQUIRED = 370;
+
+ /**
+ * SIP Response : 422
+ * The session expiration field too small
+ */
+ public static final int CODE_SIP_INTERVAL_TOO_BRIEF = 371;
+
+ /**
+ * SIP Response : 481
+ * Request received by the server does not match any dialog or transaction
+ */
+ public static final int CODE_SIP_CALL_OR_TRANS_DOES_NOT_EXIST = 372;
+
+ /**
+ * SIP Response : 482
+ * Server has detected a loop
+ */
+ public static final int CODE_SIP_LOOP_DETECTED = 373;
+
+ /**
+ * SIP Response : 483
+ * Max-Forwards value reached
+ */
+ public static final int CODE_SIP_TOO_MANY_HOPS = 374;
+
+ /**
+ * SIP Response : 485
+ * Request-URI is ambiguous
+ *
+ */
+ public static final int CODE_SIP_AMBIGUOUS = 376;
+
+ /**
+ * SIP Response : 491
+ * Server has pending request for same dialog
+ */
+ public static final int CODE_SIP_REQUEST_PENDING = 377;
+
+ /**
+ * SIP Response : 493
+ * The request cannot be decrypted by recipient
+ */
+ public static final int CODE_SIP_UNDECIPHERABLE = 378;
+
+ /**
* MEDIA (IMS -> Telephony)
*/
/**
@@ -384,6 +457,24 @@
* The call has been terminated by the network or remote user.
*/
public static final int CODE_USER_TERMINATED_BY_REMOTE = 510;
+ /**
+ * Upgrade Downgrade request rejected by
+ * Remote user if the request is MO initiated
+ * Local user if the request is MT initiated
+ */
+ public static final int CODE_USER_REJECTED_SESSION_MODIFICATION = 511;
+
+ /**
+ * Upgrade Downgrade request cacncelled by the user who initiated it
+ */
+ public static final int CODE_USER_CANCELLED_SESSION_MODIFICATION = 512;
+
+ /**
+ * UPGRADE DOWNGRADE operation failed
+ * This can happen due to failure from SIP/RTP/SDP generation or a Call end is
+ * triggered/received while Reinvite is in progress.
+ */
+ public static final int CODE_SESSION_MODIFICATION_FAILED = 1517;
/*
* UT
@@ -484,6 +575,16 @@
public static final int CODE_CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE = 1100;
/**
+ * For MultiEndPoint - Call was rejected elsewhere
+ */
+ public static final int CODE_REJECTED_ELSEWHERE = 1017;
+
+ /**
+ * Supplementary services (HOLD/RESUME) failure error codes.
+ * Values for Supplemetary services failure - Failed, Cancelled and Re-Invite collision.
+ */
+
+ /**
* Supplementary Services (HOLD/RESUME) - the command failed.
*/
public static final int CODE_SUPP_SVC_FAILED = 1201;
diff --git a/telephony/java/android/telephony/ims/RcsManager.java b/telephony/java/android/telephony/ims/RcsManager.java
new file mode 100644
index 0000000..d50b516
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsManager.java
@@ -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.
+ */
+package android.telephony.ims;
+
+import android.annotation.SystemService;
+import android.content.Context;
+
+/**
+ * The manager class for RCS related utilities.
+ * @hide
+ */
+@SystemService(Context.TELEPHONY_RCS_SERVICE)
+public class RcsManager {
+
+ private static final RcsMessageStore sRcsMessageStoreInstance = new RcsMessageStore();
+
+ /**
+ * Returns an instance of RcsMessageStore.
+ */
+ public RcsMessageStore getRcsMessageStore() {
+ return sRcsMessageStoreInstance;
+ }
+}
diff --git a/telephony/java/android/telephony/rcs/RcsManager.java b/telephony/java/android/telephony/ims/RcsMessageStore.java
similarity index 78%
rename from telephony/java/android/telephony/rcs/RcsManager.java
rename to telephony/java/android/telephony/ims/RcsMessageStore.java
index 0ef4e15..c89c0be 100644
--- a/telephony/java/android/telephony/rcs/RcsManager.java
+++ b/telephony/java/android/telephony/ims/RcsMessageStore.java
@@ -14,24 +14,20 @@
* limitations under the License.
*/
-package android.telephony.rcs;
+package android.telephony.ims;
-import android.annotation.SystemService;
-import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.Rlog;
-
-import com.android.internal.telephony.rcs.IRcs;
+import android.telephony.ims.aidl.IRcs;
/**
- * RcsManager is the application interface to RcsProvider and provides access methods to
+ * RcsMessageStore is the application interface to RcsProvider and provides access methods to
* RCS related database tables.
* @hide - TODO make this public
*/
-@SystemService(Context.TELEPHONY_RCS_SERVICE)
-public class RcsManager {
- private static final String TAG = "RcsManager";
+public class RcsMessageStore {
+ private static final String TAG = "RcsMessageStore";
private static final boolean VDBG = false;
/**
diff --git a/telephony/java/com/android/internal/telephony/rcs/IRcs.aidl b/telephony/java/android/telephony/ims/RcsThread.aidl
similarity index 63%
copy from telephony/java/com/android/internal/telephony/rcs/IRcs.aidl
copy to telephony/java/android/telephony/ims/RcsThread.aidl
index 4c289ac..79d47326 100644
--- a/telephony/java/com/android/internal/telephony/rcs/IRcs.aidl
+++ b/telephony/java/android/telephony/ims/RcsThread.aidl
@@ -1,11 +1,12 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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
+ * 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,
@@ -14,12 +15,6 @@
* limitations under the License.
*/
-package com.android.internal.telephony.rcs;
+package android.telephony;
-interface IRcs {
- // RcsManager APIs
- void deleteThread(int threadId);
-
- // RcsThread APIs
- int getMessageCount(int rcsThreadId);
-}
\ No newline at end of file
+parcelable RcsThread;
\ No newline at end of file
diff --git a/telephony/java/android/telephony/rcs/RcsThread.java b/telephony/java/android/telephony/ims/RcsThread.java
similarity index 96%
rename from telephony/java/android/telephony/rcs/RcsThread.java
rename to telephony/java/android/telephony/ims/RcsThread.java
index 83eb973..b7f440d 100644
--- a/telephony/java/android/telephony/rcs/RcsThread.java
+++ b/telephony/java/android/telephony/ims/RcsThread.java
@@ -14,14 +14,13 @@
* limitations under the License.
*/
-package android.telephony.rcs;
+package android.telephony.ims;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
-
-import com.android.internal.telephony.rcs.IRcs;
+import android.telephony.ims.aidl.IRcs;
/**
* RcsThread represents a single RCS conversation thread. It holds messages that were sent and
diff --git a/telephony/java/com/android/internal/telephony/rcs/IRcs.aidl b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
similarity index 83%
rename from telephony/java/com/android/internal/telephony/rcs/IRcs.aidl
rename to telephony/java/android/telephony/ims/aidl/IRcs.aidl
index 4c289ac..b2e2fad 100644
--- a/telephony/java/com/android/internal/telephony/rcs/IRcs.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IRcs.aidl
@@ -14,10 +14,14 @@
* limitations under the License.
*/
-package com.android.internal.telephony.rcs;
+package android.telephony.ims.aidl;
+/**
+ * RPC definition between RCS storage APIs and phone process.
+ * {@hide}
+ */
interface IRcs {
- // RcsManager APIs
+ // RcsMessageStore APIs
void deleteThread(int threadId);
// RcsThread APIs
diff --git a/telephony/java/android/telephony/rcs/RcsThread.aidl b/telephony/java/android/telephony/rcs/RcsThread.aidl
deleted file mode 100644
index e2e0da5d..0000000
--- a/telephony/java/android/telephony/rcs/RcsThread.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-**
-** 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;
-
-parcelable RcsThread;
\ No newline at end of file
diff --git a/tests/RcsTests/src/com/android/tests/rcs/RcsManagerTest.java b/tests/RcsTests/src/com/android/tests/rcs/RcsMessageStoreTest.java
similarity index 83%
rename from tests/RcsTests/src/com/android/tests/rcs/RcsManagerTest.java
rename to tests/RcsTests/src/com/android/tests/rcs/RcsMessageStoreTest.java
index 7f5f03e0d..290e04c 100644
--- a/tests/RcsTests/src/com/android/tests/rcs/RcsManagerTest.java
+++ b/tests/RcsTests/src/com/android/tests/rcs/RcsMessageStoreTest.java
@@ -16,17 +16,17 @@
package com.android.tests.rcs;
import android.support.test.runner.AndroidJUnit4;
-import android.telephony.rcs.RcsManager;
+import android.telephony.ims.RcsMessageStore;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
-public class RcsManagerTest {
+public class RcsMessageStoreTest {
//TODO(sahinc): Add meaningful tests once we have more of the implementation in place
@Test
public void testDeleteThreadDoesntCrash() {
- RcsManager mRcsManager = new RcsManager();
- mRcsManager.deleteThread(0);
+ RcsMessageStore mRcsMessageStore = new RcsMessageStore();
+ mRcsMessageStore.deleteThread(0);
}
}
diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java
index 436dd85..151b559 100644
--- a/tests/net/java/android/net/apf/ApfTest.java
+++ b/tests/net/java/android/net/apf/ApfTest.java
@@ -1048,12 +1048,17 @@
4, // Protocol size: 4
0, 2 // Opcode: reply (2)
};
- private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ETH_HEADER_LEN + 24;
+ private static final int ARP_SOURCE_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 14;
+ private static final int ARP_TARGET_IP_ADDRESS_OFFSET = ARP_HEADER_OFFSET + 24;
private static final byte[] MOCK_IPV4_ADDR = {10, 0, 0, 1};
private static final byte[] MOCK_BROADCAST_IPV4_ADDR = {10, 0, 31, (byte) 255}; // prefix = 19
private static final byte[] MOCK_MULTICAST_IPV4_ADDR = {(byte) 224, 0, 0, 1};
private static final byte[] ANOTHER_IPV4_ADDR = {10, 0, 0, 2};
+ private static final byte[] IPV4_SOURCE_ADDR = {10, 0, 0, 3};
+ private static final byte[] ANOTHER_IPV4_SOURCE_ADDR = {(byte) 192, 0, 2, 1};
+ private static final byte[] BUG_PROBE_SOURCE_ADDR1 = {0, 0, 1, 2};
+ private static final byte[] BUG_PROBE_SOURCE_ADDR2 = {3, 4, 0, 0};
private static final byte[] IPV4_ANY_HOST_ADDR = {0, 0, 0, 0};
// Helper to initialize a default apfFilter.
@@ -1399,10 +1404,16 @@
assertVerdict(filterResult, program, arpRequestBroadcast(ANOTHER_IPV4_ADDR));
assertDrop(program, arpRequestBroadcast(IPV4_ANY_HOST_ADDR));
+ // Verify ARP reply packets from different source ip
+ assertDrop(program, arpReply(IPV4_ANY_HOST_ADDR, IPV4_ANY_HOST_ADDR));
+ assertPass(program, arpReply(ANOTHER_IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR));
+ assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR1, IPV4_ANY_HOST_ADDR));
+ assertPass(program, arpReply(BUG_PROBE_SOURCE_ADDR2, IPV4_ANY_HOST_ADDR));
+
// Verify unicast ARP reply packet is always accepted.
- assertPass(program, arpReplyUnicast(MOCK_IPV4_ADDR));
- assertPass(program, arpReplyUnicast(ANOTHER_IPV4_ADDR));
- assertPass(program, arpReplyUnicast(IPV4_ANY_HOST_ADDR));
+ assertPass(program, arpReply(IPV4_SOURCE_ADDR, MOCK_IPV4_ADDR));
+ assertPass(program, arpReply(IPV4_SOURCE_ADDR, ANOTHER_IPV4_ADDR));
+ assertPass(program, arpReply(IPV4_SOURCE_ADDR, IPV4_ANY_HOST_ADDR));
// Verify GARP reply packets are always filtered
assertDrop(program, garpReply());
@@ -1431,19 +1442,20 @@
apfFilter.shutdown();
}
- private static byte[] arpRequestBroadcast(byte[] tip) {
+ private static byte[] arpReply(byte[] sip, byte[] tip) {
ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
- put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
+ put(packet, ARP_SOURCE_IP_ADDRESS_OFFSET, sip);
put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
return packet.array();
}
- private static byte[] arpReplyUnicast(byte[] tip) {
+ private static byte[] arpRequestBroadcast(byte[] tip) {
ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_ARP);
- put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REPLY_HEADER);
+ put(packet, ETH_DEST_ADDR_OFFSET, ETH_BROADCAST_MAC_ADDRESS);
+ put(packet, ARP_HEADER_OFFSET, ARP_IPV4_REQUEST_HEADER);
put(packet, ARP_TARGET_IP_ADDRESS_OFFSET, tip);
return packet.array();
}
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index 8081812..bca9be7 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -71,7 +71,6 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
-import android.net.NetworkRequest;
import android.net.NetworkState;
import android.net.NetworkUtils;
import android.net.RouteInfo;
@@ -130,10 +129,6 @@
private static final String TEST_USB_IFNAME = "test_rndis0";
private static final String TEST_WLAN_IFNAME = "test_wlan0";
- // Actual contents of the request don't matter for this test. The lack of
- // any specific TRANSPORT_* is sufficient to identify this request.
- private static final NetworkRequest mDefaultRequest = new NetworkRequest.Builder().build();
-
@Mock private ApplicationInfo mApplicationInfo;
@Mock private Context mContext;
@Mock private INetworkManagementService mNMService;
@@ -257,11 +252,6 @@
isTetheringSupportedCalls++;
return true;
}
-
- @Override
- public NetworkRequest getDefaultNetworkRequest() {
- return mDefaultRequest;
- }
}
private static NetworkState buildMobileUpstreamState(boolean withIPv4, boolean withIPv6,
@@ -496,7 +486,7 @@
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
verifyNoMoreInteractions(mWifiManager);
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
- verify(mUpstreamNetworkMonitor, times(1)).start(any(NetworkRequest.class));
+ verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
// TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
@@ -730,7 +720,7 @@
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
verifyNoMoreInteractions(mWifiManager);
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_TETHER);
- verify(mUpstreamNetworkMonitor, times(1)).start(any(NetworkRequest.class));
+ verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
// In tethering mode, in the default configuration, an explicit request
// for a mobile network is also made.
verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
diff --git a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
index a22cbd4..0afd607 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
@@ -24,6 +24,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -53,7 +54,6 @@
import android.net.NetworkRequest;
import android.net.NetworkState;
import android.net.util.SharedLog;
-
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -65,7 +65,6 @@
import org.junit.runner.RunWith;
import org.junit.Test;
import org.mockito.Mock;
-import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
@@ -126,7 +125,7 @@
}
@Test
- public void testDoesNothingBeforeStarted() {
+ public void testDoesNothingBeforeTrackDefaultAndStarted() throws Exception {
assertTrue(mCM.hasNoCallbacks());
assertFalse(mUNM.mobileNetworkRequested());
@@ -138,37 +137,40 @@
@Test
public void testDefaultNetworkIsTracked() throws Exception {
- assertEquals(0, mCM.trackingDefault.size());
+ assertTrue(mCM.hasNoCallbacks());
+ mUNM.startTrackDefaultNetwork(mDefaultRequest);
- mUNM.start(mDefaultRequest);
+ mUNM.startObserveAllNetworks();
assertEquals(1, mCM.trackingDefault.size());
mUNM.stop();
- assertTrue(mCM.hasNoCallbacks());
+ assertTrue(mCM.onlyHasDefaultCallbacks());
}
@Test
public void testListensForAllNetworks() throws Exception {
assertTrue(mCM.listening.isEmpty());
- mUNM.start(mDefaultRequest);
+ mUNM.startTrackDefaultNetwork(mDefaultRequest);
+ mUNM.startObserveAllNetworks();
assertFalse(mCM.listening.isEmpty());
assertTrue(mCM.isListeningForAll());
mUNM.stop();
- assertTrue(mCM.hasNoCallbacks());
+ assertTrue(mCM.onlyHasDefaultCallbacks());
}
@Test
public void testCallbacksRegistered() {
- mUNM.start(mDefaultRequest);
- verify(mCM, times(1)).registerNetworkCallback(
- any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
+ mUNM.startTrackDefaultNetwork(mDefaultRequest);
verify(mCM, times(1)).requestNetwork(
eq(mDefaultRequest), any(NetworkCallback.class), any(Handler.class));
+ mUNM.startObserveAllNetworks();
+ verify(mCM, times(1)).registerNetworkCallback(
+ any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
mUNM.stop();
- verify(mCM, times(2)).unregisterNetworkCallback(any(NetworkCallback.class));
+ verify(mCM, times(1)).unregisterNetworkCallback(any(NetworkCallback.class));
}
@Test
@@ -176,7 +178,7 @@
assertFalse(mUNM.mobileNetworkRequested());
assertEquals(0, mCM.requested.size());
- mUNM.start(mDefaultRequest);
+ mUNM.startObserveAllNetworks();
assertFalse(mUNM.mobileNetworkRequested());
assertEquals(0, mCM.requested.size());
@@ -199,11 +201,9 @@
assertFalse(mUNM.mobileNetworkRequested());
assertEquals(0, mCM.requested.size());
- mUNM.start(mDefaultRequest);
+ mUNM.startObserveAllNetworks();
verify(mCM, times(1)).registerNetworkCallback(
any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
- verify(mCM, times(1)).requestNetwork(
- eq(mDefaultRequest), any(NetworkCallback.class), any(Handler.class));
assertFalse(mUNM.mobileNetworkRequested());
assertEquals(0, mCM.requested.size());
@@ -227,7 +227,7 @@
assertTrue(mCM.isDunRequested());
mUNM.stop();
- verify(mCM, times(3)).unregisterNetworkCallback(any(NetworkCallback.class));
+ verify(mCM, times(2)).unregisterNetworkCallback(any(NetworkCallback.class));
verifyNoMoreInteractions(mCM);
}
@@ -237,7 +237,7 @@
assertFalse(mUNM.mobileNetworkRequested());
assertEquals(0, mCM.requested.size());
- mUNM.start(mDefaultRequest);
+ mUNM.startObserveAllNetworks();
assertFalse(mUNM.mobileNetworkRequested());
assertEquals(0, mCM.requested.size());
@@ -257,7 +257,7 @@
@Test
public void testUpdateMobileRequiresDun() throws Exception {
- mUNM.start(mDefaultRequest);
+ mUNM.startObserveAllNetworks();
// Test going from no-DUN to DUN correctly re-registers callbacks.
mUNM.updateMobileRequiresDun(false);
@@ -285,7 +285,8 @@
final Collection<Integer> preferredTypes = new ArrayList<>();
preferredTypes.add(TYPE_WIFI);
- mUNM.start(mDefaultRequest);
+ mUNM.startTrackDefaultNetwork(mDefaultRequest);
+ mUNM.startObserveAllNetworks();
// There are no networks, so there is nothing to select.
assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
@@ -350,7 +351,8 @@
@Test
public void testGetCurrentPreferredUpstream() throws Exception {
- mUNM.start(mDefaultRequest);
+ mUNM.startTrackDefaultNetwork(mDefaultRequest);
+ mUNM.startObserveAllNetworks();
mUNM.updateMobileRequiresDun(false);
// [0] Mobile connects, DUN not required -> mobile selected.
@@ -389,7 +391,8 @@
@Test
public void testLocalPrefixes() throws Exception {
- mUNM.start(mDefaultRequest);
+ mUNM.startTrackDefaultNetwork(mDefaultRequest);
+ mUNM.startObserveAllNetworks();
// [0] Test minimum set of local prefixes.
Set<IpPrefix> local = mUNM.getLocalPrefixes();
@@ -521,11 +524,19 @@
}
boolean hasNoCallbacks() {
- return allCallbacks.isEmpty() &&
- trackingDefault.isEmpty() &&
- listening.isEmpty() &&
- requested.isEmpty() &&
- legacyTypeMap.isEmpty();
+ return allCallbacks.isEmpty()
+ && trackingDefault.isEmpty()
+ && listening.isEmpty()
+ && requested.isEmpty()
+ && legacyTypeMap.isEmpty();
+ }
+
+ boolean onlyHasDefaultCallbacks() {
+ return (allCallbacks.size() == 1)
+ && (trackingDefault.size() == 1)
+ && listening.isEmpty()
+ && requested.isEmpty()
+ && legacyTypeMap.isEmpty();
}
boolean isListeningForAll() {
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index ebdcdfd..61174d9 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -47,7 +47,8 @@
fields(that.fields),
primaryFields(that.primaryFields),
exclusiveField(that.exclusiveField),
- uidField(that.uidField) {}
+ uidField(that.uidField),
+ binaryFields(that.binaryFields) {}
AtomDecl::AtomDecl(int c, const string& n, const string& m)
:code(c),
@@ -116,6 +117,9 @@
if (field->message_type()->full_name() ==
"android.os.statsd.AttributionNode") {
return JAVA_TYPE_ATTRIBUTION_CHAIN;
+ } else if (field->options().GetExtension(os::statsd::log_mode) ==
+ os::statsd::LogMode::MODE_BYTES) {
+ return JAVA_TYPE_BYTE_ARRAY;
} else {
return JAVA_TYPE_OBJECT;
}
@@ -185,6 +189,8 @@
for (map<int, const FieldDescriptor *>::const_iterator it = fields.begin();
it != fields.end(); it++) {
const FieldDescriptor *field = it->second;
+ bool isBinaryField = field->options().GetExtension(os::statsd::log_mode) ==
+ os::statsd::LogMode::MODE_BYTES;
java_type_t javaType = java_type(field);
@@ -198,12 +204,19 @@
field->name().c_str());
errorCount++;
continue;
- } else if (javaType == JAVA_TYPE_BYTE_ARRAY) {
+ } else if (javaType == JAVA_TYPE_BYTE_ARRAY && !isBinaryField) {
print_error(field, "Raw bytes type not allowed for field: %s\n",
field->name().c_str());
errorCount++;
continue;
}
+
+ if (isBinaryField && javaType != JAVA_TYPE_BYTE_ARRAY) {
+ print_error(field, "Cannot mark field %s as bytes.\n",
+ field->name().c_str());
+ errorCount++;
+ continue;
+ }
}
// Check that if there's an attribution chain, it's at position 1.
@@ -228,12 +241,16 @@
it != fields.end(); it++) {
const FieldDescriptor *field = it->second;
java_type_t javaType = java_type(field);
+ bool isBinaryField = field->options().GetExtension(os::statsd::log_mode) ==
+ os::statsd::LogMode::MODE_BYTES;
AtomField atField(field->name(), javaType);
if (javaType == JAVA_TYPE_ENUM) {
// All enums are treated as ints when it comes to function signatures.
signature->push_back(JAVA_TYPE_INT);
collate_enums(*field->enum_type(), &atField);
+ } else if (javaType == JAVA_TYPE_OBJECT && isBinaryField) {
+ signature->push_back(JAVA_TYPE_BYTE_ARRAY);
} else {
signature->push_back(javaType);
}
@@ -275,6 +292,10 @@
errorCount++;
}
}
+ // Binary field validity is already checked above.
+ if (isBinaryField) {
+ atomDecl->binaryFields.push_back(it->first);
+ }
}
return errorCount;
diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h
index 5d2c302..a8b270c 100644
--- a/tools/stats_log_api_gen/Collation.h
+++ b/tools/stats_log_api_gen/Collation.h
@@ -86,6 +86,8 @@
int uidField = 0;
+ vector<int> binaryFields;
+
AtomDecl();
AtomDecl(const AtomDecl& that);
AtomDecl(int code, const string& name, const string& message);
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index e519909..485fc46 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -68,6 +68,8 @@
return "double";
case JAVA_TYPE_STRING:
return "char const*";
+ case JAVA_TYPE_BYTE_ARRAY:
+ return "char const*";
default:
return "UNKNOWN";
}
@@ -90,6 +92,8 @@
return "double";
case JAVA_TYPE_STRING:
return "java.lang.String";
+ case JAVA_TYPE_BYTE_ARRAY:
+ return "byte[]";
default:
return "UNKNOWN";
}
@@ -200,13 +204,40 @@
}
fprintf(out, " return options;\n");
- fprintf(out, " }\n");
+ fprintf(out, "}\n");
fprintf(out,
"const std::map<int, StateAtomFieldOptions> "
"AtomsInfo::kStateAtomsFieldOptions = "
"getStateAtomFieldOptions();\n");
+ fprintf(out,
+ "static std::map<int, std::vector<int>> "
+ "getBinaryFieldAtoms() {\n");
+ fprintf(out, " std::map<int, std::vector<int>> options;\n");
+ for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+ atom != atoms.decls.end(); atom++) {
+ if (atom->binaryFields.size() == 0) {
+ continue;
+ }
+ fprintf(out,
+ "\n // Adding binary fields for atom "
+ "(%d)%s\n",
+ atom->code, atom->name.c_str());
+
+ for (const auto& field : atom->binaryFields) {
+ fprintf(out, " options[static_cast<int>(%s)].push_back(%d);\n",
+ make_constant_name(atom->name).c_str(), field);
+ }
+ }
+
+ fprintf(out, " return options;\n");
+ fprintf(out, "}\n");
+
+ fprintf(out,
+ "const std::map<int, std::vector<int>> "
+ "AtomsInfo::kBytesFieldAtoms = "
+ "getBinaryFieldAtoms();\n");
fprintf(out, "int64_t lastRetryTimestampNs = -1;\n");
fprintf(out, "const int64_t kMinRetryIntervalNs = NS_PER_SEC * 60 * 20; // 20 minutes\n");
@@ -235,6 +266,9 @@
chainField.name.c_str(), chainField.name.c_str());
}
}
+ } else if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+ fprintf(out, ", %s arg%d, size_t arg%d_length",
+ cpp_type_name(*arg), argIndex, argIndex);
} else {
fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
}
@@ -277,6 +311,10 @@
fprintf(out, " event.end();\n");
fprintf(out, " }\n");
fprintf(out, " event.end();\n\n");
+ } else if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+ fprintf(out,
+ " event.AppendCharArray(arg%d, arg%d_length);\n",
+ argIndex, argIndex);
} else {
if (*arg == JAVA_TYPE_STRING) {
fprintf(out, " if (arg%d == NULL) {\n", argIndex);
@@ -317,6 +355,9 @@
chainField.name.c_str(), chainField.name.c_str());
}
}
+ } else if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+ fprintf(out, ", %s arg%d, size_t arg%d_length",
+ cpp_type_name(*arg), argIndex, argIndex);
} else {
fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
}
@@ -343,6 +384,8 @@
chainField.name.c_str(), chainField.name.c_str());
}
}
+ } else if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+ fprintf(out, ", arg%d, arg%d_length", argIndex, argIndex);
} else {
fprintf(out, ", arg%d", argIndex);
}
@@ -491,6 +534,10 @@
chainField.name.c_str(), chainField.name.c_str());
}
}
+ } else if (field->javaType == JAVA_TYPE_BYTE_ARRAY) {
+ fprintf(out, ", %s %s, size_t %s_length",
+ cpp_type_name(field->javaType), field->name.c_str(),
+ field->name.c_str());
} else {
fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str());
}
@@ -518,6 +565,9 @@
chainField.name.c_str(), chainField.name.c_str());
}
}
+ } else if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+ fprintf(out, ", %s arg%d, size_t arg%d_length",
+ cpp_type_name(*arg), argIndex, argIndex);
} else {
fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
}
@@ -600,6 +650,9 @@
fprintf(out,
" const static std::map<int, StateAtomFieldOptions> "
"kStateAtomsFieldOptions;\n");
+ fprintf(out,
+ " const static std::map<int, std::vector<int>> "
+ "kBytesFieldAtoms;");
fprintf(out, "};\n");
fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n",
@@ -632,6 +685,8 @@
field != atom.fields.end(); field++) {
if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
fprintf(out, ", android.os.WorkSource workSource");
+ } else if (field->javaType == JAVA_TYPE_BYTE_ARRAY) {
+ fprintf(out, ", byte[] %s", field->name.c_str());
} else {
fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str());
}
@@ -821,6 +876,8 @@
return "jdouble";
case JAVA_TYPE_STRING:
return "jstring";
+ case JAVA_TYPE_BYTE_ARRAY:
+ return "jbyteArray";
default:
return "UNKNOWN";
}
@@ -868,6 +925,9 @@
case JAVA_TYPE_ATTRIBUTION_CHAIN:
result += "_AttributionChain";
break;
+ case JAVA_TYPE_BYTE_ARRAY:
+ result += "_bytes";
+ break;
default:
result += "_UNKNOWN";
break;
@@ -893,6 +953,8 @@
return "D";
case JAVA_TYPE_STRING:
return "Ljava/lang/String;";
+ case JAVA_TYPE_BYTE_ARRAY:
+ return "[B";
default:
return "UNKNOWN";
}
@@ -960,6 +1022,32 @@
fprintf(out, " } else {\n");
fprintf(out, " str%d = NULL;\n", argIndex);
fprintf(out, " }\n");
+ } else if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+ hadStringOrChain = true;
+ fprintf(out, " jbyte* jbyte_array%d;\n", argIndex);
+ fprintf(out, " const char* str%d;\n", argIndex);
+ fprintf(out, " int str%d_length = 0;\n", argIndex);
+ fprintf(out,
+ " if (arg%d != NULL && env->GetArrayLength(arg%d) > "
+ "0) {\n",
+ argIndex, argIndex);
+ fprintf(out,
+ " jbyte_array%d = "
+ "env->GetByteArrayElements(arg%d, NULL);\n",
+ argIndex, argIndex);
+ fprintf(out,
+ " str%d_length = env->GetArrayLength(arg%d);\n",
+ argIndex, argIndex);
+ fprintf(out,
+ " str%d = "
+ "reinterpret_cast<char*>(env->GetByteArrayElements(arg%"
+ "d, NULL));\n",
+ argIndex, argIndex);
+ fprintf(out, " } else {\n");
+ fprintf(out, " jbyte_array%d = NULL;\n", argIndex);
+ fprintf(out, " str%d = NULL;\n", argIndex);
+ fprintf(out, " }\n");
+
} else if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
hadStringOrChain = true;
for (auto chainField : attributionDecl.fields) {
@@ -1026,8 +1114,15 @@
}
}
} else {
- const char *argName = (*arg == JAVA_TYPE_STRING) ? "str" : "arg";
+ const char* argName = (*arg == JAVA_TYPE_STRING ||
+ *arg == JAVA_TYPE_BYTE_ARRAY)
+ ? "str"
+ : "arg";
fprintf(out, ", (%s)%s%d", cpp_type_name(*arg), argName, argIndex);
+
+ if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+ fprintf(out, ", %s%d_length", argName, argIndex);
+ }
}
argIndex++;
}
@@ -1043,6 +1138,13 @@
fprintf(out, " env->ReleaseStringUTFChars(arg%d, str%d);\n",
argIndex, argIndex);
fprintf(out, " }\n");
+ } else if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+ fprintf(out, " if (str%d != NULL) { \n", argIndex);
+ fprintf(out,
+ " env->ReleaseByteArrayElements(arg%d, "
+ "jbyte_array%d, 0);\n",
+ argIndex, argIndex);
+ fprintf(out, " }\n");
} else if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
for (auto chainField : attributionDecl.fields) {
if (chainField.javaType == JAVA_TYPE_INT) {
diff --git a/tools/stats_log_api_gen/test.proto b/tools/stats_log_api_gen/test.proto
index 264a865e..188b765 100644
--- a/tools/stats_log_api_gen/test.proto
+++ b/tools/stats_log_api_gen/test.proto
@@ -109,6 +109,28 @@
oneof event { BadAttributionNodePositionAtom bad = 1; }
}
+message GoodEventWithBinaryFieldAtom {
+ oneof event { GoodBinaryFieldAtom field1 = 1; }
+}
+
+message ComplexField {
+ optional string str = 1;
+}
+
+message GoodBinaryFieldAtom {
+ optional int32 field1 = 1;
+ optional ComplexField bf = 2 [(android.os.statsd.log_mode) = MODE_BYTES];
+}
+
+message BadEventWithBinaryFieldAtom {
+ oneof event { BadBinaryFieldAtom field1 = 1; }
+}
+
+message BadBinaryFieldAtom {
+ optional int32 field1 = 1;
+ optional ComplexField bf = 2;
+}
+
message BadStateAtoms {
oneof event {
BadStateAtom1 bad1 = 1;
diff --git a/tools/stats_log_api_gen/test_collation.cpp b/tools/stats_log_api_gen/test_collation.cpp
index 1936d96..ad3bffac 100644
--- a/tools/stats_log_api_gen/test_collation.cpp
+++ b/tools/stats_log_api_gen/test_collation.cpp
@@ -212,5 +212,19 @@
EXPECT_EQ(0, errorCount);
}
+TEST(CollationTest, PassOnGoodBinaryFieldAtom) {
+ Atoms atoms;
+ int errorCount =
+ collate_atoms(GoodEventWithBinaryFieldAtom::descriptor(), &atoms);
+ EXPECT_EQ(0, errorCount);
+}
+
+TEST(CollationTest, FailOnBadBinaryFieldAtom) {
+ Atoms atoms;
+ int errorCount =
+ collate_atoms(BadEventWithBinaryFieldAtom::descriptor(), &atoms);
+ EXPECT_TRUE(errorCount > 0);
+}
+
} // namespace stats_log_api_gen
} // namespace android
\ No newline at end of file