Merge "Add userId to the package name API."
diff --git a/core/java/android/annotation/UnsupportedAppUsage.java b/core/java/android/annotation/UnsupportedAppUsage.java
index a454df5..204d71d 100644
--- a/core/java/android/annotation/UnsupportedAppUsage.java
+++ b/core/java/android/annotation/UnsupportedAppUsage.java
@@ -83,8 +83,9 @@
* <p>Possible values are:
* <ul>
* <li>
- * {@link android.os.Build.VERSION_CODES#O} or {@link android.os.Build.VERSION_CODES#P},
- * to limit access to apps targeting these SDKs (or earlier).
+ * An API level like {@link android.os.Build.VERSION_CODES#O} - in which case the API is
+ * available up to and including the specified release. Or, in other words, the API is
+ * blacklisted (unavailable) from the next API level from the one specified.
* </li>
* <li>
* absent (default value) - All apps can access this API, but doing so may result in
@@ -94,10 +95,6 @@
*
* </ul>
*
- * Note, if this is set to {@link android.os.Build.VERSION_CODES#O}, apps targeting O
- * maintenance releases will also be allowed to use the API, and similarly for any future
- * maintenance releases of P.
- *
* @return The maximum value for an apps targetSdkVersion in order to access this API.
*/
int maxTargetSdk() default Integer.MAX_VALUE;
diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java
index 30868bf..97e3f52 100644
--- a/core/java/android/bluetooth/le/ScanRecord.java
+++ b/core/java/android/bluetooth/le/ScanRecord.java
@@ -154,7 +154,7 @@
}
/**
- * Returns the local name of the BLE device. The is a UTF-8 encoded string.
+ * Returns the local name of the BLE device. This is a UTF-8 encoded string.
*/
@Nullable
public String getDeviceName() {
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 3e325b7..e3259ff 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -57,6 +57,9 @@
private static final String TAG = "NetworkCapabilities";
private static final int INVALID_UID = -1;
+ // Set to true when private DNS is broken.
+ private boolean mPrivateDnsBroken;
+
/**
* @hide
*/
@@ -86,6 +89,7 @@
mUids = null;
mEstablishingVpnAppUid = INVALID_UID;
mSSID = null;
+ mPrivateDnsBroken = false;
}
/**
@@ -104,6 +108,7 @@
mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid;
mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities;
mSSID = nc.mSSID;
+ mPrivateDnsBroken = nc.mPrivateDnsBroken;
}
/**
@@ -557,6 +562,9 @@
}
if (mLinkUpBandwidthKbps != 0 || mLinkDownBandwidthKbps != 0) return "link bandwidth";
if (hasSignalStrength()) return "signalStrength";
+ if (isPrivateDnsBroken()) {
+ return "privateDnsBroken";
+ }
return null;
}
@@ -1443,7 +1451,8 @@
&& equalsSpecifier(that)
&& equalsTransportInfo(that)
&& equalsUids(that)
- && equalsSSID(that));
+ && equalsSSID(that)
+ && equalsPrivateDnsBroken(that));
}
@Override
@@ -1460,7 +1469,8 @@
+ (mSignalStrength * 29)
+ Objects.hashCode(mUids) * 31
+ Objects.hashCode(mSSID) * 37
- + Objects.hashCode(mTransportInfo) * 41;
+ + Objects.hashCode(mTransportInfo) * 41
+ + Objects.hashCode(mPrivateDnsBroken) * 43;
}
@Override
@@ -1479,6 +1489,7 @@
dest.writeInt(mSignalStrength);
dest.writeArraySet(mUids);
dest.writeString(mSSID);
+ dest.writeBoolean(mPrivateDnsBroken);
}
public static final @android.annotation.NonNull Creator<NetworkCapabilities> CREATOR =
@@ -1498,6 +1509,7 @@
netCap.mUids = (ArraySet<UidRange>) in.readArraySet(
null /* ClassLoader, null for default */);
netCap.mSSID = in.readString();
+ netCap.mPrivateDnsBroken = in.readBoolean();
return netCap;
}
@Override
@@ -1555,6 +1567,10 @@
sb.append(" SSID: ").append(mSSID);
}
+ if (mPrivateDnsBroken) {
+ sb.append(" Private DNS is broken");
+ }
+
sb.append("]");
return sb.toString();
}
@@ -1706,4 +1722,28 @@
public boolean isMetered() {
return !hasCapability(NET_CAPABILITY_NOT_METERED);
}
+
+ /**
+ * Check if private dns is broken.
+ *
+ * @return {@code true} if {@code mPrivateDnsBroken} is set when private DNS is broken.
+ * @hide
+ */
+ public boolean isPrivateDnsBroken() {
+ return mPrivateDnsBroken;
+ }
+
+ /**
+ * Set mPrivateDnsBroken to true when private dns is broken.
+ *
+ * @param broken the status of private DNS to be set.
+ * @hide
+ */
+ public void setPrivateDnsBroken(boolean broken) {
+ mPrivateDnsBroken = broken;
+ }
+
+ private boolean equalsPrivateDnsBroken(NetworkCapabilities nc) {
+ return mPrivateDnsBroken == nc.mPrivateDnsBroken;
+ }
}
diff --git a/core/java/android/net/NetworkMisc.java b/core/java/android/net/NetworkMisc.java
index 9ba3bd9..4ad52d5 100644
--- a/core/java/android/net/NetworkMisc.java
+++ b/core/java/android/net/NetworkMisc.java
@@ -77,6 +77,12 @@
*/
public boolean skip464xlat;
+ /**
+ * Set to true if the PRIVATE_DNS_BROKEN notification has shown for this network.
+ * Reset this bit when private DNS mode is changed from strict mode to opportunistic/off mode.
+ */
+ public boolean hasShownBroken;
+
public NetworkMisc() {
}
diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java
index d2f22bf..ff8b135 100644
--- a/core/java/android/service/euicc/EuiccService.java
+++ b/core/java/android/service/euicc/EuiccService.java
@@ -29,7 +29,6 @@
import android.telephony.euicc.DownloadableSubscription;
import android.telephony.euicc.EuiccInfo;
import android.telephony.euicc.EuiccManager.OtaStatus;
-import android.util.ArraySet;
import android.util.Log;
import java.lang.annotation.Retention;
@@ -252,18 +251,6 @@
public static final int RESULT_FIRST_USER = 1;
/**
- * List of all valid resolution actions for validation purposes.
- * @hide
- */
- public static final ArraySet<String> RESOLUTION_ACTIONS;
- static {
- RESOLUTION_ACTIONS = new ArraySet<>();
- RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM);
- RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_NO_PRIVILEGES);
- RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_RESOLVABLE_ERRORS);
- }
-
- /**
* Boolean extra for resolution actions indicating whether the user granted consent.
* This is used and set by the implementation and used in {@code EuiccOperation}.
*/
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e132c36..936ff0c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3431,6 +3431,15 @@
<!-- A notification is shown when the user connects to a Wi-Fi network and the system detects that that network has no Internet access. This is the notification's message. -->
<string name="wifi_no_internet_detailed">Tap for options</string>
+ <!-- A notification is shown when the user connects to a mobile network without internet access. This is the notification's title. -->
+ <string name="mobile_no_internet">Mobile network has no internet access</string>
+
+ <!-- A notification is shown when the user connects to a non-mobile and non-wifi network without internet access. This is the notification's title. -->
+ <string name="other_networks_no_internet">Network has no internet access</string>
+
+ <!-- A notification is shown when connected network without internet due to private dns validation failed. This is the notification's message. [CHAR LIMIT=NONE] -->
+ <string name="private_dns_broken_detailed">Private DNS server cannot be accessed</string>
+
<!-- A notification is shown after the user logs in to a captive portal network, to indicate that the network should now have internet connectivity. This is the message of notification. [CHAR LIMIT=50] -->
<string name="captive_portal_logged_in_detailed">Connected</string>
<!-- A notification is shown when the user connects to a network that doesn't have access to some services (e.g. Push notifications may not work). This is the notification's title. [CHAR LIMIT=50] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index fa58c7a..aacc74f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -590,9 +590,12 @@
<java-symbol type="string" name="menu_space_shortcut_label" />
<java-symbol type="string" name="menu_shift_shortcut_label" />
<java-symbol type="string" name="menu_sym_shortcut_label" />
+ <java-symbol type="string" name="mobile_no_internet" />
<java-symbol type="string" name="notification_title" />
+ <java-symbol type="string" name="other_networks_no_internet" />
<java-symbol type="string" name="permission_request_notification_with_subtitle" />
<java-symbol type="string" name="prepend_shortcut_label" />
+ <java-symbol type="string" name="private_dns_broken_detailed" />
<java-symbol type="string" name="paste_as_plain_text" />
<java-symbol type="string" name="replace" />
<java-symbol type="string" name="undo" />
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index f71c8b0..2d1c61c 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -90,7 +90,7 @@
<shortcode country="cz" premium="9\\d{6,7}" free="116\\d{3}" />
<!-- Germany: 4-5 digits plus 1232xxx (premium codes from http://www.vodafone.de/infofaxe/537.pdf and http://premiumdienste.eplus.de/pdf/kodex.pdf), plus EU. To keep the premium regex from being too large, it only includes payment processors that have been used by SMS malware, with the regular pattern matching the other premium short codes. -->
- <shortcode country="de" pattern="\\d{4,5}|1232\\d{3}" premium="11(?:111|833)|1232(?:013|021|060|075|286|358)|118(?:44|80|86)|20[25]00|220(?:21|22|88|99)|221(?:14|21)|223(?:44|53|77)|224[13]0|225(?:20|59|90)|226(?:06|10|20|26|30|40|56|70)|227(?:07|33|39|66|76|78|79|88|99)|228(?:08|11|66|77)|23300|30030|3[12347]000|330(?:33|55|66)|33(?:233|331|366|533)|34(?:34|567)|37000|40(?:040|123|444|[3568]00)|41(?:010|414)|44(?:000|044|344|44[24]|544)|50005|50100|50123|50555|51000|52(?:255|783)|54(?:100|2542)|55(?:077|[24]00|222|333|55|[12369]55)|56(?:789|886)|60800|6[13]000|66(?:[12348]66|566|766|777|88|999)|68888|70(?:07|123|777)|76766|77(?:007|070|222|444|[567]77)|80(?:008|123|888)|82(?:002|[378]00|323|444|472|474|488|727)|83(?:005|[169]00|333|830)|84(?:141|300|32[34]|343|488|499|777|888)|85888|86(?:188|566|640|644|650|677|868|888)|870[24]9|871(?:23|[49]9)|872(?:1[0-8]|49|99)|87499|875(?:49|55|99)|876(?:0[1367]|1[1245678]|54|99)|877(?:00|99)|878(?:15|25|3[567]|8[12])|87999|880(?:08|44|55|77|99)|88688|888(?:03|10|8|89)|8899|90(?:009|999)|99999" free="116\\d{3}|81214|81215|47529|70296|83782|3011|73240" />
+ <shortcode country="de" pattern="\\d{4,5}|1232\\d{3}" premium="11(?:111|833)|1232(?:013|021|060|075|286|358)|118(?:44|80|86)|20[25]00|220(?:21|22|88|99)|221(?:14|21)|223(?:44|53|77)|224[13]0|225(?:20|59|90)|226(?:06|10|20|26|30|40|56|70)|227(?:07|33|39|66|76|78|79|88|99)|228(?:08|11|66|77)|23300|30030|3[12347]000|330(?:33|55|66)|33(?:233|331|366|533)|34(?:34|567)|37000|40(?:040|123|444|[3568]00)|41(?:010|414)|44(?:000|044|344|44[24]|544)|50005|50100|50123|50555|51000|52(?:255|783)|54(?:100|2542)|55(?:077|[24]00|222|333|55|[12369]55)|56(?:789|886)|60800|6[13]000|66(?:[12348]66|566|766|777|88|999)|68888|70(?:07|123|777)|76766|77(?:007|070|222|444|[567]77)|80(?:008|123|888)|82(?:002|[378]00|323|444|472|474|488|727)|83(?:005|[169]00|333|830)|84(?:141|300|32[34]|343|488|499|777|888)|85888|86(?:188|566|640|644|650|677|868|888)|870[24]9|871(?:23|[49]9)|872(?:1[0-8]|49|99)|87499|875(?:49|55|99)|876(?:0[1367]|1[1245678]|54|99)|877(?:00|99)|878(?:15|25|3[567]|8[12])|87999|880(?:08|44|55|77|99)|88688|888(?:03|10|8|89)|8899|90(?:009|999)|99999" free="116\\d{3}|81214|81215|47529|70296|83782|3011|73240|72438" />
<!-- Denmark: see http://iprs.webspacecommerce.com/Denmark-Premium-Rate-Numbers -->
<shortcode country="dk" pattern="\\d{4,5}" premium="1\\d{3}" free="116\\d{3}|4665" />
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 53bc65d..bb731a8 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -16,6 +16,7 @@
package android.media;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
@@ -26,6 +27,8 @@
import android.media.audiopolicy.AudioMix;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Map;
@@ -431,6 +434,50 @@
public static final int DEAD_OBJECT = -6;
public static final int WOULD_BLOCK = -7;
+ /** @hide */
+ @IntDef({
+ SUCCESS,
+ ERROR,
+ BAD_VALUE,
+ INVALID_OPERATION,
+ PERMISSION_DENIED,
+ NO_INIT,
+ DEAD_OBJECT,
+ WOULD_BLOCK
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AudioSystemError {}
+
+ /**
+ * Convert an int error value to its String value for readability.
+ * Accepted error values are the java AudioSystem errors, matching android_media_AudioErrors.h,
+ * which map onto the native status_t type.
+ * @param error one of the java AudioSystem errors
+ * @return a human-readable string
+ */
+ public static String audioSystemErrorToString(@AudioSystemError int error) {
+ switch(error) {
+ case SUCCESS:
+ return "SUCCESS";
+ case ERROR:
+ return "ERROR";
+ case BAD_VALUE:
+ return "BAD_VALUE";
+ case INVALID_OPERATION:
+ return "INVALID_OPERATION";
+ case PERMISSION_DENIED:
+ return "PERMISSION_DENIED";
+ case NO_INIT:
+ return "NO_INIT";
+ case DEAD_OBJECT:
+ return "DEAD_OBJECT";
+ case WOULD_BLOCK:
+ return "WOULD_BLOCK";
+ default:
+ return ("unknown error:" + error);
+ }
+ }
+
/*
* AudioPolicyService methods
*/
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 39474e1..01f1250 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -853,6 +853,10 @@
Log.v(TAG, "notifyVolumeAdjust: " + adjustment);
}
}
+
+ public void notifyUnregistration() {
+ setRegistration(null);
+ }
};
//==================================================
diff --git a/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl b/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
index 107e7cd..1d58151 100644
--- a/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
+++ b/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl
@@ -34,4 +34,8 @@
// callback for volume events
void notifyVolumeAdjust(int adjustment);
+
+ // callback for unregistration (e.g. if policy couldn't automatically be re-registered after
+ // an audioserver crash)
+ void notifyUnregistration();
}
diff --git a/media/java/android/media/midi/MidiDeviceInfo.aidl b/media/java/android/media/midi/MidiDeviceInfo.aidl
index 5b2ac9b..a248204 100644
--- a/media/java/android/media/midi/MidiDeviceInfo.aidl
+++ b/media/java/android/media/midi/MidiDeviceInfo.aidl
@@ -16,4 +16,4 @@
package android.media.midi;
-parcelable MidiDeviceInfo cpp_header "media/MidiDeviceInfo.h";
+parcelable MidiDeviceInfo cpp_header "MidiDeviceInfo.h";
diff --git a/media/native/midi/Android.bp b/media/native/midi/Android.bp
index 58317ed..8f3e12e 100644
--- a/media/native/midi/Android.bp
+++ b/media/native/midi/Android.bp
@@ -17,6 +17,7 @@
srcs: [
"amidi.cpp",
+ "MidiDeviceInfo.cpp",
":IMidiDeviceServer.aidl",
],
@@ -31,12 +32,14 @@
"-fvisibility=hidden",
],
+ header_libs: [
+ "media_ndk_headers",
+ ],
+
shared_libs: [
"liblog",
"libbinder",
"libutils",
- "libmedia",
- "libmediandk",
"libandroid_runtime",
],
diff --git a/media/native/midi/MidiDeviceInfo.cpp b/media/native/midi/MidiDeviceInfo.cpp
new file mode 100644
index 0000000..ac68d26
--- /dev/null
+++ b/media/native/midi/MidiDeviceInfo.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "MidiDeviceInfo"
+
+#include <MidiDeviceInfo.h>
+
+#include <binder/Parcel.h>
+#include <log/log.h>
+#include <utils/Errors.h>
+#include <utils/String16.h>
+
+namespace android {
+namespace media {
+namespace midi {
+
+// The constant values need to be kept in sync with MidiDeviceInfo.java.
+// static
+const char* const MidiDeviceInfo::PROPERTY_NAME = "name";
+const char* const MidiDeviceInfo::PROPERTY_MANUFACTURER = "manufacturer";
+const char* const MidiDeviceInfo::PROPERTY_PRODUCT = "product";
+const char* const MidiDeviceInfo::PROPERTY_VERSION = "version";
+const char* const MidiDeviceInfo::PROPERTY_SERIAL_NUMBER = "serial_number";
+const char* const MidiDeviceInfo::PROPERTY_ALSA_CARD = "alsa_card";
+const char* const MidiDeviceInfo::PROPERTY_ALSA_DEVICE = "alsa_device";
+
+String16 MidiDeviceInfo::getProperty(const char* propertyName) {
+ String16 value;
+ if (mProperties.getString(String16(propertyName), &value)) {
+ return value;
+ } else {
+ return String16();
+ }
+}
+
+#define RETURN_IF_FAILED(calledOnce) \
+ { \
+ status_t returnStatus = calledOnce; \
+ if (returnStatus) { \
+ ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
+ return returnStatus; \
+ } \
+ }
+
+status_t MidiDeviceInfo::writeToParcel(Parcel* parcel) const {
+ // Needs to be kept in sync with code in MidiDeviceInfo.java
+ RETURN_IF_FAILED(parcel->writeInt32(mType));
+ RETURN_IF_FAILED(parcel->writeInt32(mId));
+ RETURN_IF_FAILED(parcel->writeInt32((int32_t)mInputPortNames.size()));
+ RETURN_IF_FAILED(parcel->writeInt32((int32_t)mOutputPortNames.size()));
+ RETURN_IF_FAILED(writeStringVector(parcel, mInputPortNames));
+ RETURN_IF_FAILED(writeStringVector(parcel, mOutputPortNames));
+ RETURN_IF_FAILED(parcel->writeInt32(mIsPrivate ? 1 : 0));
+ RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
+ // This corresponds to "extra" properties written by Java code
+ RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
+ return OK;
+}
+
+status_t MidiDeviceInfo::readFromParcel(const Parcel* parcel) {
+ // Needs to be kept in sync with code in MidiDeviceInfo.java
+ RETURN_IF_FAILED(parcel->readInt32(&mType));
+ RETURN_IF_FAILED(parcel->readInt32(&mId));
+ int32_t inputPortCount;
+ RETURN_IF_FAILED(parcel->readInt32(&inputPortCount));
+ int32_t outputPortCount;
+ RETURN_IF_FAILED(parcel->readInt32(&outputPortCount));
+ RETURN_IF_FAILED(readStringVector(parcel, &mInputPortNames, inputPortCount));
+ RETURN_IF_FAILED(readStringVector(parcel, &mOutputPortNames, outputPortCount));
+ int32_t isPrivate;
+ RETURN_IF_FAILED(parcel->readInt32(&isPrivate));
+ mIsPrivate = isPrivate == 1;
+ RETURN_IF_FAILED(mProperties.readFromParcel(parcel));
+ // Ignore "extra" properties as they may contain Java Parcelables
+ return OK;
+}
+
+status_t MidiDeviceInfo::readStringVector(
+ const Parcel* parcel, Vector<String16> *vectorPtr, size_t defaultLength) {
+ std::unique_ptr<std::vector<std::unique_ptr<String16>>> v;
+ status_t result = parcel->readString16Vector(&v);
+ if (result != OK) return result;
+ vectorPtr->clear();
+ if (v.get() != nullptr) {
+ for (const auto& iter : *v) {
+ if (iter.get() != nullptr) {
+ vectorPtr->push_back(*iter);
+ } else {
+ vectorPtr->push_back(String16());
+ }
+ }
+ } else {
+ vectorPtr->resize(defaultLength);
+ }
+ return OK;
+}
+
+status_t MidiDeviceInfo::writeStringVector(Parcel* parcel, const Vector<String16>& vector) const {
+ std::vector<String16> v;
+ for (size_t i = 0; i < vector.size(); ++i) {
+ v.push_back(vector[i]);
+ }
+ return parcel->writeString16Vector(v);
+}
+
+// Vector does not define operator==
+static inline bool areVectorsEqual(const Vector<String16>& lhs, const Vector<String16>& rhs) {
+ if (lhs.size() != rhs.size()) return false;
+ for (size_t i = 0; i < lhs.size(); ++i) {
+ if (lhs[i] != rhs[i]) return false;
+ }
+ return true;
+}
+
+bool operator==(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs) {
+ return (lhs.mType == rhs.mType && lhs.mId == rhs.mId &&
+ areVectorsEqual(lhs.mInputPortNames, rhs.mInputPortNames) &&
+ areVectorsEqual(lhs.mOutputPortNames, rhs.mOutputPortNames) &&
+ lhs.mProperties == rhs.mProperties &&
+ lhs.mIsPrivate == rhs.mIsPrivate);
+}
+
+} // namespace midi
+} // namespace media
+} // namespace android
diff --git a/media/native/midi/MidiDeviceInfo.h b/media/native/midi/MidiDeviceInfo.h
new file mode 100644
index 0000000..5b4a241
--- /dev/null
+++ b/media/native/midi/MidiDeviceInfo.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_MEDIA_MIDI_DEVICE_INFO_H
+#define ANDROID_MEDIA_MIDI_DEVICE_INFO_H
+
+#include <binder/Parcelable.h>
+#include <binder/PersistableBundle.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+namespace android {
+namespace media {
+namespace midi {
+
+class MidiDeviceInfo : public Parcelable {
+public:
+ MidiDeviceInfo() = default;
+ virtual ~MidiDeviceInfo() = default;
+ MidiDeviceInfo(const MidiDeviceInfo& midiDeviceInfo) = default;
+
+ status_t writeToParcel(Parcel* parcel) const override;
+ status_t readFromParcel(const Parcel* parcel) override;
+
+ int getType() const { return mType; }
+ int getUid() const { return mId; }
+ bool isPrivate() const { return mIsPrivate; }
+ const Vector<String16>& getInputPortNames() const { return mInputPortNames; }
+ const Vector<String16>& getOutputPortNames() const { return mOutputPortNames; }
+ String16 getProperty(const char* propertyName);
+
+ // The constants need to be kept in sync with MidiDeviceInfo.java
+ enum {
+ TYPE_USB = 1,
+ TYPE_VIRTUAL = 2,
+ TYPE_BLUETOOTH = 3,
+ };
+ static const char* const PROPERTY_NAME;
+ static const char* const PROPERTY_MANUFACTURER;
+ static const char* const PROPERTY_PRODUCT;
+ static const char* const PROPERTY_VERSION;
+ static const char* const PROPERTY_SERIAL_NUMBER;
+ static const char* const PROPERTY_ALSA_CARD;
+ static const char* const PROPERTY_ALSA_DEVICE;
+
+ friend bool operator==(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs);
+ friend bool operator!=(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs) {
+ return !(lhs == rhs);
+ }
+
+private:
+ status_t readStringVector(
+ const Parcel* parcel, Vector<String16> *vectorPtr, size_t defaultLength);
+ status_t writeStringVector(Parcel* parcel, const Vector<String16>& vector) const;
+
+ int32_t mType;
+ int32_t mId;
+ Vector<String16> mInputPortNames;
+ Vector<String16> mOutputPortNames;
+ os::PersistableBundle mProperties;
+ bool mIsPrivate;
+};
+
+} // namespace midi
+} // namespace media
+} // namespace android
+
+#endif // ANDROID_MEDIA_MIDI_DEVICE_INFO_H
diff --git a/media/native/midi/amidi.cpp b/media/native/midi/amidi.cpp
index 1e9a194..e7c4d99 100644
--- a/media/native/midi/amidi.cpp
+++ b/media/native/midi/amidi.cpp
@@ -26,7 +26,7 @@
#include <core_jni_helpers.h>
#include "android/media/midi/BpMidiDeviceServer.h"
-#include "media/MidiDeviceInfo.h"
+#include "MidiDeviceInfo.h"
#include "include/amidi/AMidi.h"
#include "amidi_internal.h"
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
index 81c5bcd..642dc82 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
@@ -35,7 +35,6 @@
import android.net.http.SslError;
import android.os.Bundle;
import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
import android.telephony.SubscriptionManager;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -477,11 +476,11 @@
}
private static void logd(String s) {
- Rlog.d(TAG, s);
+ Log.d(TAG, s);
}
private static void loge(String s) {
- Rlog.d(TAG, s);
+ Log.d(TAG, s);
}
}
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java
index 02c61d7..46b1d5f 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java
@@ -19,7 +19,6 @@
import android.content.Intent;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
import android.text.TextUtils;
import android.util.Log;
@@ -27,7 +26,6 @@
import com.android.internal.util.ArrayUtils;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
/**
@@ -44,7 +42,7 @@
private static final String INTER_GROUP_DELIMITER = "\\s*:\\s*";
private static final String TAG = CustomConfigLoader.class.getSimpleName();
- private static final boolean VDBG = Rlog.isLoggable(TAG, Log.VERBOSE);
+ private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
/**
* loads and parses the carrier config, return a list of carrier action for the given signal
@@ -70,7 +68,7 @@
// return an empty list if no match found
List<Integer> actionList = new ArrayList<>();
if (carrierConfigManager == null) {
- Rlog.e(TAG, "load carrier config failure with carrier config manager uninitialized");
+ Log.e(TAG, "load carrier config failure with carrier config manager uninitialized");
return actionList;
}
PersistableBundle b = carrierConfigManager.getConfig();
@@ -101,8 +99,8 @@
.EXTRA_DEFAULT_NETWORK_AVAILABLE_KEY, false));
break;
default:
- Rlog.e(TAG, "load carrier config failure with un-configured key: " +
- intent.getAction());
+ Log.e(TAG, "load carrier config failure with un-configured key: "
+ + intent.getAction());
break;
}
if (!ArrayUtils.isEmpty(configs)) {
@@ -111,12 +109,12 @@
matchConfig(config, arg1, arg2, actionList);
if (!actionList.isEmpty()) {
// return the first match
- if (VDBG) Rlog.d(TAG, "found match action list: " + actionList.toString());
+ if (VDBG) Log.d(TAG, "found match action list: " + actionList.toString());
return actionList;
}
}
}
- Rlog.d(TAG, "no matching entry for signal: " + intent.getAction() + "arg1: " + arg1
+ Log.d(TAG, "no matching entry for signal: " + intent.getAction() + "arg1: " + arg1
+ "arg2: " + arg2);
}
return actionList;
@@ -166,7 +164,7 @@
try {
actionList.add(Integer.parseInt(idx));
} catch (NumberFormatException e) {
- Rlog.e(TAG, "NumberFormatException(string: " + idx + " config:" + config + "): "
+ Log.e(TAG, "NumberFormatException(string: " + idx + " config:" + config + "): "
+ e);
}
}
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 0e91839..bdfa217 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -127,6 +127,9 @@
<!-- Summary for Connected wifi network without internet -->
<string name="wifi_connected_no_internet">Connected, no internet</string>
+ <!-- Summary for connected network without internet due to private dns validation failed [CHAR LIMIT=NONE] -->
+ <string name="private_dns_broken">Private DNS server cannot be accessed</string>
+
<!-- Summary for connected wifi network with partial internet connectivity [CHAR LIMIT=50] -->
<string name="wifi_limited_connection">Limited connection</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index f16fb1c..9e71189 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -50,6 +50,7 @@
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
@@ -1569,7 +1570,13 @@
NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY)) {
return context.getString(R.string.wifi_limited_connection);
} else if (!nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
- return context.getString(R.string.wifi_connected_no_internet);
+ final String mode = Settings.Global.getString(context.getContentResolver(),
+ Settings.Global.PRIVATE_DNS_MODE);
+ if (nc.isPrivateDnsBroken()) {
+ return context.getString(R.string.private_dns_broken);
+ } else {
+ return context.getString(R.string.wifi_connected_no_internet);
+ }
}
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 5352936..b11585a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -31,6 +31,7 @@
import android.net.wifi.WifiSsid;
import android.os.Handler;
import android.os.Looper;
+import android.provider.Settings;
import com.android.settingslib.R;
@@ -163,7 +164,13 @@
statusLabel = mContext.getString(R.string.wifi_limited_connection);
return;
} else if (!networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
- statusLabel = mContext.getString(R.string.wifi_status_no_internet);
+ final String mode = Settings.Global.getString(mContext.getContentResolver(),
+ Settings.Global.PRIVATE_DNS_MODE);
+ if (networkCapabilities.isPrivateDnsBroken()) {
+ statusLabel = mContext.getString(R.string.private_dns_broken);
+ } else {
+ statusLabel = mContext.getString(R.string.wifi_status_no_internet);
+ }
return;
}
}
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index ffbf1ae..ef071a4 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -249,6 +249,8 @@
NOTE_NETWORK_LOGGED_IN = 744;
// A partial connectivity network was detected during network validation
NOTE_NETWORK_PARTIAL_CONNECTIVITY = 745;
+ // Private DNS is broken in strict mode
+ NOTE_NETWORK_PRIVATE_DNS_BROKEN = 746;
// Notify the user that their work profile has been deleted
// Package: android
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 0bb72cb..ce0e9e7 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -26,6 +26,7 @@
import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.ConnectivityManager.isNetworkTypeValid;
+import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
@@ -528,6 +529,15 @@
private static final int EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY = 45;
/**
+ * Event for NetworkMonitor to inform ConnectivityService that the probe status has changed.
+ * Both of the arguments are bitmasks, and the value of bits come from
+ * INetworkMonitor.NETWORK_VALIDATION_PROBE_*.
+ * arg1 = A bitmask to describe which probes are completed.
+ * arg2 = A bitmask to describe which probes are successful.
+ */
+ public static final int EVENT_PROBE_STATUS_CHANGED = 46;
+
+ /**
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
* should be shown.
*/
@@ -2663,6 +2673,41 @@
switch (msg.what) {
default:
return false;
+ case EVENT_PROBE_STATUS_CHANGED: {
+ final Integer netId = (Integer) msg.obj;
+ final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(netId);
+ if (nai == null) {
+ break;
+ }
+ final boolean probePrivateDnsCompleted =
+ ((msg.arg1 & NETWORK_VALIDATION_PROBE_PRIVDNS) != 0);
+ final boolean privateDnsBroken =
+ ((msg.arg2 & NETWORK_VALIDATION_PROBE_PRIVDNS) == 0);
+ if (probePrivateDnsCompleted) {
+ if (nai.networkCapabilities.isPrivateDnsBroken() != privateDnsBroken) {
+ nai.networkCapabilities.setPrivateDnsBroken(privateDnsBroken);
+ final int oldScore = nai.getCurrentScore();
+ updateCapabilities(oldScore, nai, nai.networkCapabilities);
+ }
+ // Only show the notification when the private DNS is broken and the
+ // PRIVATE_DNS_BROKEN notification hasn't shown since last valid.
+ if (privateDnsBroken && !nai.networkMisc.hasShownBroken) {
+ showNetworkNotification(nai, NotificationType.PRIVATE_DNS_BROKEN);
+ }
+ nai.networkMisc.hasShownBroken = privateDnsBroken;
+ } else if (nai.networkCapabilities.isPrivateDnsBroken()) {
+ // If probePrivateDnsCompleted is false but nai.networkCapabilities says
+ // private DNS is broken, it means this network is being reevaluated.
+ // Either probing private DNS is not necessary any more or it hasn't been
+ // done yet. In either case, the networkCapabilities should be updated to
+ // reflect the new status.
+ nai.networkCapabilities.setPrivateDnsBroken(false);
+ final int oldScore = nai.getCurrentScore();
+ updateCapabilities(oldScore, nai, nai.networkCapabilities);
+ nai.networkMisc.hasShownBroken = false;
+ }
+ break;
+ }
case EVENT_NETWORK_TESTED: {
final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
if (nai == null) break;
@@ -2705,14 +2750,20 @@
if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
if (valid) {
handleFreshlyValidatedNetwork(nai);
- // Clear NO_INTERNET, PARTIAL_CONNECTIVITY and LOST_INTERNET
- // notifications if network becomes valid.
+ // Clear NO_INTERNET, PRIVATE_DNS_BROKEN, PARTIAL_CONNECTIVITY and
+ // LOST_INTERNET notifications if network becomes valid.
mNotifier.clearNotification(nai.network.netId,
NotificationType.NO_INTERNET);
mNotifier.clearNotification(nai.network.netId,
NotificationType.LOST_INTERNET);
mNotifier.clearNotification(nai.network.netId,
NotificationType.PARTIAL_CONNECTIVITY);
+ mNotifier.clearNotification(nai.network.netId,
+ NotificationType.PRIVATE_DNS_BROKEN);
+ // If network becomes valid, the hasShownBroken should be reset for
+ // that network so that the notification will be fired when the private
+ // DNS is broken again.
+ nai.networkMisc.hasShownBroken = false;
}
} else if (partialConnectivityChanged) {
updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
@@ -2863,6 +2914,13 @@
}
@Override
+ public void notifyProbeStatusChanged(int probesCompleted, int probesSucceeded) {
+ mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
+ EVENT_PROBE_STATUS_CHANGED,
+ probesCompleted, probesSucceeded, new Integer(mNetId)));
+ }
+
+ @Override
public void showProvisioningNotification(String action, String packageName) {
final Intent intent = new Intent(action);
intent.setPackage(packageName);
@@ -3679,6 +3737,11 @@
// High priority because it is only displayed for explicitly selected networks.
highPriority = true;
break;
+ case PRIVATE_DNS_BROKEN:
+ action = Settings.ACTION_WIRELESS_SETTINGS;
+ // High priority because we should let user know why there is no internet.
+ highPriority = true;
+ break;
case LOST_INTERNET:
action = ConnectivityManager.ACTION_PROMPT_LOST_VALIDATION;
// High priority because it could help the user avoid unexpected data usage.
@@ -3696,7 +3759,7 @@
}
Intent intent = new Intent(action);
- if (type != NotificationType.LOGGED_IN) {
+ if (type != NotificationType.LOGGED_IN && type != NotificationType.PRIVATE_DNS_BROKEN) {
intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.netId), null));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClassName("com.android.settings",
@@ -5162,6 +5225,13 @@
ns.assertValidFromUid(Binder.getCallingUid());
}
+ private void ensureValid(NetworkCapabilities nc) {
+ ensureValidNetworkSpecifier(nc);
+ if (nc.isPrivateDnsBroken()) {
+ throw new IllegalArgumentException("Can't request broken private DNS");
+ }
+ }
+
@Override
public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
@@ -5195,7 +5265,7 @@
if (timeoutMs < 0) {
throw new IllegalArgumentException("Bad timeout specified");
}
- ensureValidNetworkSpecifier(networkCapabilities);
+ ensureValid(networkCapabilities);
NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
nextNetworkRequestId(), type);
@@ -5337,7 +5407,7 @@
// There is no need to do this for requests because an app without CHANGE_NETWORK_STATE
// can't request networks.
restrictBackgroundRequestForCaller(nc);
- ensureValidNetworkSpecifier(nc);
+ ensureValid(nc);
NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
NetworkRequest.Type.LISTEN);
@@ -5355,7 +5425,7 @@
if (!hasWifiNetworkListenPermission(networkCapabilities)) {
enforceAccessPermission();
}
- ensureValidNetworkSpecifier(networkCapabilities);
+ ensureValid(networkCapabilities);
ensureSufficientPermissionsForRequest(networkCapabilities,
Binder.getCallingPid(), Binder.getCallingUid());
@@ -5841,6 +5911,7 @@
} else {
newNc.removeCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY);
}
+ newNc.setPrivateDnsBroken(nai.networkCapabilities.isPrivateDnsBroken());
return newNc;
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index e26cbc4..055a4bd 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1018,7 +1018,14 @@
synchronized (mAudioPolicies) {
for (AudioPolicyProxy policy : mAudioPolicies.values()) {
- policy.connectMixes();
+ final int status = policy.connectMixes();
+ if (status != AudioSystem.SUCCESS) {
+ // note that PERMISSION_DENIED may also indicate trouble getting to APService
+ Log.e(TAG, "onAudioServerDied: error "
+ + AudioSystem.audioSystemErrorToString(status)
+ + " when connecting mixes for policy " + policy.toLogFriendlyString());
+ policy.release();
+ }
}
}
@@ -7007,16 +7014,8 @@
}
public void binderDied() {
- synchronized (mAudioPolicies) {
- Log.i(TAG, "audio policy " + mPolicyCallback + " died");
- release();
- mAudioPolicies.remove(mPolicyCallback.asBinder());
- }
- if (mIsVolumeController) {
- synchronized (mExtVolumeControllerLock) {
- mExtVolumeController = null;
- }
- }
+ Log.i(TAG, "audio policy " + mPolicyCallback + " died");
+ release();
}
String getRegistrationId() {
@@ -7040,9 +7039,20 @@
Log.e(TAG, "Fail to unregister Audiopolicy callback from MediaProjection");
}
}
+ if (mIsVolumeController) {
+ synchronized (mExtVolumeControllerLock) {
+ mExtVolumeController = null;
+ }
+ }
final long identity = Binder.clearCallingIdentity();
AudioSystem.registerPolicyMixes(mMixes, false);
Binder.restoreCallingIdentity(identity);
+ synchronized (mAudioPolicies) {
+ mAudioPolicies.remove(mPolicyCallback.asBinder());
+ }
+ try {
+ mPolicyCallback.notifyUnregistration();
+ } catch (RemoteException e) { }
}
boolean hasMixAffectingUsage(int usage, int excludedFlags) {
@@ -7093,7 +7103,7 @@
}
}
- int connectMixes() {
+ @AudioSystem.AudioSystemError int connectMixes() {
final long identity = Binder.clearCallingIdentity();
int status = AudioSystem.registerPolicyMixes(mMixes, true);
Binder.restoreCallingIdentity(identity);
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 077c405..d13e675 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -53,7 +53,8 @@
NO_INTERNET(SystemMessage.NOTE_NETWORK_NO_INTERNET),
LOGGED_IN(SystemMessage.NOTE_NETWORK_LOGGED_IN),
PARTIAL_CONNECTIVITY(SystemMessage.NOTE_NETWORK_PARTIAL_CONNECTIVITY),
- SIGN_IN(SystemMessage.NOTE_NETWORK_SIGN_IN);
+ SIGN_IN(SystemMessage.NOTE_NETWORK_SIGN_IN),
+ PRIVATE_DNS_BROKEN(SystemMessage.NOTE_NETWORK_PRIVATE_DNS_BROKEN);
public final int eventId;
@@ -175,13 +176,23 @@
}
Resources r = Resources.getSystem();
- CharSequence title;
- CharSequence details;
+ final CharSequence title;
+ final CharSequence details;
int icon = getIcon(transportType, notifyType);
if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) {
title = r.getString(R.string.wifi_no_internet,
WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID()));
details = r.getString(R.string.wifi_no_internet_detailed);
+ } else if (notifyType == NotificationType.PRIVATE_DNS_BROKEN) {
+ if (transportType == TRANSPORT_CELLULAR) {
+ title = r.getString(R.string.mobile_no_internet);
+ } else if (transportType == TRANSPORT_WIFI) {
+ title = r.getString(R.string.wifi_no_internet,
+ WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID()));
+ } else {
+ title = r.getString(R.string.other_networks_no_internet);
+ }
+ details = r.getString(R.string.private_dns_broken_detailed);
} else if (notifyType == NotificationType.PARTIAL_CONNECTIVITY
&& transportType == TRANSPORT_WIFI) {
title = r.getString(R.string.network_partial_connectivity,
@@ -357,8 +368,10 @@
}
switch (t) {
case SIGN_IN:
- return 5;
+ return 6;
case PARTIAL_CONNECTIVITY:
+ return 5;
+ case PRIVATE_DNS_BROKEN:
return 4;
case NO_INTERNET:
return 3;
diff --git a/services/net/java/android/net/netlink/InetDiagMessage.java b/services/net/java/android/net/netlink/InetDiagMessage.java
index 31a2556..ca07630 100644
--- a/services/net/java/android/net/netlink/InetDiagMessage.java
+++ b/services/net/java/android/net/netlink/InetDiagMessage.java
@@ -26,6 +26,7 @@
import static android.system.OsConstants.IPPROTO_UDP;
import static android.system.OsConstants.NETLINK_INET_DIAG;
+import android.annotation.Nullable;
import android.net.util.SocketUtils;
import android.system.ErrnoException;
import android.util.Log;
@@ -53,7 +54,35 @@
private static final int TIMEOUT_MS = 500;
public static byte[] InetDiagReqV2(int protocol, InetSocketAddress local,
- InetSocketAddress remote, int family, short flags) {
+ InetSocketAddress remote, int family, short flags) {
+ return InetDiagReqV2(protocol, local, remote, family, flags, 0 /* pad */,
+ 0 /* idiagExt */, StructInetDiagReqV2.INET_DIAG_REQ_V2_ALL_STATES);
+ }
+
+ /**
+ * Construct an inet_diag_req_v2 message. This method will throw {@code NullPointerException}
+ * if local and remote are not both null or both non-null.
+ *
+ * @param protocol the request protocol type. This should be set to one of IPPROTO_TCP,
+ * IPPROTO_UDP, or IPPROTO_UDPLITE.
+ * @param local local socket address of the target socket. This will be packed into a
+ * {@Code StructInetDiagSockId}. Request to diagnose for all sockets if both of
+ * local or remote address is null.
+ * @param remote remote socket address of the target socket. This will be packed into a
+ * {@Code StructInetDiagSockId}. Request to diagnose for all sockets if both of
+ * local or remote address is null.
+ * @param family the ip family of the request message. This should be set to either AF_INET or
+ * AF_INET6 for IPv4 or IPv6 sockets respectively.
+ * @param flags message flags. See <linux_src>/include/uapi/linux/netlink.h.
+ * @param pad for raw socket protocol specification.
+ * @param idiagExt a set of flags defining what kind of extended information to report.
+ * @param state a bit mask that defines a filter of socket states.
+ *
+ * @return bytes array representation of the message
+ **/
+ public static byte[] InetDiagReqV2(int protocol, @Nullable InetSocketAddress local,
+ @Nullable InetSocketAddress remote, int family, short flags, int pad, int idiagExt,
+ int state) throws NullPointerException {
final byte[] bytes = new byte[StructNlMsgHdr.STRUCT_SIZE + StructInetDiagReqV2.STRUCT_SIZE];
final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
byteBuffer.order(ByteOrder.nativeOrder());
@@ -63,9 +92,9 @@
nlMsgHdr.nlmsg_type = SOCK_DIAG_BY_FAMILY;
nlMsgHdr.nlmsg_flags = flags;
nlMsgHdr.pack(byteBuffer);
+ final StructInetDiagReqV2 inetDiagReqV2 =
+ new StructInetDiagReqV2(protocol, local, remote, family, pad, idiagExt, state);
- final StructInetDiagReqV2 inetDiagReqV2 = new StructInetDiagReqV2(protocol, local, remote,
- family);
inetDiagReqV2.pack(byteBuffer);
return bytes;
}
diff --git a/services/net/java/android/net/netlink/StructInetDiagReqV2.java b/services/net/java/android/net/netlink/StructInetDiagReqV2.java
index 49a9325..2268113 100644
--- a/services/net/java/android/net/netlink/StructInetDiagReqV2.java
+++ b/services/net/java/android/net/netlink/StructInetDiagReqV2.java
@@ -16,10 +16,10 @@
package android.net.netlink;
-import static java.nio.ByteOrder.BIG_ENDIAN;
+import android.annotation.Nullable;
+
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
/**
* struct inet_diag_req_v2
@@ -40,41 +40,58 @@
public class StructInetDiagReqV2 {
public static final int STRUCT_SIZE = 8 + StructInetDiagSockId.STRUCT_SIZE;
- private final byte sdiag_family;
- private final byte sdiag_protocol;
- private final StructInetDiagSockId id;
- private final int INET_DIAG_REQ_V2_ALL_STATES = (int) 0xffffffff;
-
+ private final byte mSdiagFamily;
+ private final byte mSdiagProtocol;
+ private final byte mIdiagExt;
+ private final byte mPad;
+ private final StructInetDiagSockId mId;
+ private final int mState;
+ public static final int INET_DIAG_REQ_V2_ALL_STATES = (int) 0xffffffff;
public StructInetDiagReqV2(int protocol, InetSocketAddress local, InetSocketAddress remote,
- int family) {
- sdiag_family = (byte) family;
- sdiag_protocol = (byte) protocol;
- id = new StructInetDiagSockId(local, remote);
+ int family) {
+ this(protocol, local, remote, family, 0 /* pad */, 0 /* extension */,
+ INET_DIAG_REQ_V2_ALL_STATES);
+ }
+
+ public StructInetDiagReqV2(int protocol, @Nullable InetSocketAddress local,
+ @Nullable InetSocketAddress remote, int family, int pad, int extension, int state)
+ throws NullPointerException {
+ mSdiagFamily = (byte) family;
+ mSdiagProtocol = (byte) protocol;
+ // Request for all sockets if no specific socket is requested. Specify the local and remote
+ // socket address information for target request socket.
+ if ((local == null) != (remote == null)) {
+ throw new NullPointerException("Local and remote must be both null or both non-null");
+ }
+ mId = ((local != null && remote != null) ? new StructInetDiagSockId(local, remote) : null);
+ mPad = (byte) pad;
+ mIdiagExt = (byte) extension;
+ mState = state;
}
public void pack(ByteBuffer byteBuffer) {
// The ByteOrder must have already been set by the caller.
- byteBuffer.put((byte) sdiag_family);
- byteBuffer.put((byte) sdiag_protocol);
- byteBuffer.put((byte) 0);
- byteBuffer.put((byte) 0);
- byteBuffer.putInt(INET_DIAG_REQ_V2_ALL_STATES);
- id.pack(byteBuffer);
+ byteBuffer.put((byte) mSdiagFamily);
+ byteBuffer.put((byte) mSdiagProtocol);
+ byteBuffer.put((byte) mIdiagExt);
+ byteBuffer.put((byte) mPad);
+ byteBuffer.putInt(mState);
+ if (mId != null) mId.pack(byteBuffer);
}
@Override
public String toString() {
- final String familyStr = NetlinkConstants.stringForAddressFamily(sdiag_family);
- final String protocolStr = NetlinkConstants.stringForAddressFamily(sdiag_protocol);
+ final String familyStr = NetlinkConstants.stringForAddressFamily(mSdiagFamily);
+ final String protocolStr = NetlinkConstants.stringForAddressFamily(mSdiagProtocol);
return "StructInetDiagReqV2{ "
+ "sdiag_family{" + familyStr + "}, "
+ "sdiag_protocol{" + protocolStr + "}, "
- + "idiag_ext{" + 0 + ")}, "
- + "pad{" + 0 + "}, "
- + "idiag_states{" + Integer.toHexString(INET_DIAG_REQ_V2_ALL_STATES) + "}, "
- + id.toString()
+ + "idiag_ext{" + mIdiagExt + ")}, "
+ + "pad{" + mPad + "}, "
+ + "idiag_states{" + Integer.toHexString(mState) + "}, "
+ + ((mId != null) ? mId.toString() : "inet_diag_sockid=null")
+ "}";
}
}
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 3f348a4..60290e3 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -2049,6 +2049,10 @@
return "DISCONNECTING";
case STATE_SELECT_PHONE_ACCOUNT:
return "SELECT_PHONE_ACCOUNT";
+ case STATE_SIMULATED_RINGING:
+ return "SIMULATED_RINGING";
+ case STATE_AUDIO_PROCESSING:
+ return "AUDIO_PROCESSING";
default:
Log.w(Call.class, "Unknown state %d", state);
return "UNKNOWN";
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index 2ca0d1a8..1569112 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -271,7 +271,7 @@
.addCapability(NET_CAPABILITY_NOT_METERED);
assertParcelingIsLossless(netCap);
netCap.setSSID(TEST_SSID);
- assertParcelSane(netCap, 11);
+ assertParcelSane(netCap, 12);
}
@Test
diff --git a/tests/net/java/android/net/netlink/InetDiagSocketTest.java b/tests/net/java/android/net/netlink/InetDiagSocketTest.java
index 46e27c1..1f2bb0a 100644
--- a/tests/net/java/android/net/netlink/InetDiagSocketTest.java
+++ b/tests/net/java/android/net/netlink/InetDiagSocketTest.java
@@ -30,6 +30,7 @@
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.app.Instrumentation;
import android.content.Context;
@@ -283,6 +284,107 @@
assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg);
}
+ // Hexadecimal representation of InetDiagReqV2 request with extension, INET_DIAG_INFO.
+ private static final String INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX =
+ // struct nlmsghdr
+ "48000000" + // length = 72
+ "1400" + // type = SOCK_DIAG_BY_FAMILY
+ "0100" + // flags = NLM_F_REQUEST
+ "00000000" + // seqno
+ "00000000" + // pid (0 == kernel)
+ // struct inet_diag_req_v2
+ "02" + // family = AF_INET
+ "06" + // protcol = IPPROTO_TCP
+ "02" + // idiag_ext = INET_DIAG_INFO
+ "00" + // pad
+ "ffffffff" + // idiag_states
+ // inet_diag_sockid
+ "3039" + // idiag_sport = 12345
+ "d431" + // idiag_dport = 54321
+ "01020304000000000000000000000000" + // idiag_src = 1.2.3.4
+ "08080404000000000000000000000000" + // idiag_dst = 8.8.4.4
+ "00000000" + // idiag_if
+ "ffffffffffffffff"; // idiag_cookie = INET_DIAG_NOCOOKIE
+
+ private static final byte[] INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES =
+ HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_HEX.toCharArray(), false);
+ private static final int TCP_ALL_STATES = 0xffffffff;
+ @Test
+ public void testInetDiagReqV2TcpInetWithExt() throws Exception {
+ InetSocketAddress local = new InetSocketAddress(
+ InetAddress.getByName("1.2.3.4"), 12345);
+ InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"),
+ 54321);
+ byte[] msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET,
+ NLM_F_REQUEST, 0 /* pad */, 2 /* idiagExt */, TCP_ALL_STATES);
+
+ assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET_INET_DIAG_BYTES, msg);
+
+ local = new InetSocketAddress(
+ InetAddress.getByName("fe80::86c9:b2ff:fe6a:ed4b"), 42462);
+ remote = new InetSocketAddress(InetAddress.getByName("8.8.8.8"),
+ 47473);
+ msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, remote, AF_INET6,
+ NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
+
+ assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_BYTES, msg);
+ }
+
+ // Hexadecimal representation of InetDiagReqV2 request with no socket specified.
+ private static final String INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX =
+ // struct nlmsghdr
+ "48000000" + // length = 72
+ "1400" + // type = SOCK_DIAG_BY_FAMILY
+ "0100" + // flags = NLM_F_REQUEST
+ "00000000" + // seqno
+ "00000000" + // pid (0 == kernel)
+ // struct inet_diag_req_v2
+ "0a" + // family = AF_INET6
+ "06" + // protcol = IPPROTO_TCP
+ "00" + // idiag_ext
+ "00" + // pad
+ "ffffffff" + // idiag_states
+ // inet_diag_sockid
+ "0000" + // idiag_sport
+ "0000" + // idiag_dport
+ "00000000000000000000000000000000" + // idiag_src
+ "00000000000000000000000000000000" + // idiag_dst
+ "00000000" + // idiag_if
+ "0000000000000000"; // idiag_cookie
+
+ private static final byte[] INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES =
+ HexEncoding.decode(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFIED_HEX.toCharArray(), false);
+
+ @Test
+ public void testInetDiagReqV2TcpInet6NoIdSpecified() throws Exception {
+ InetSocketAddress local = new InetSocketAddress(
+ InetAddress.getByName("fe80::fe6a:ed4b"), 12345);
+ InetSocketAddress remote = new InetSocketAddress(InetAddress.getByName("8.8.4.4"),
+ 54321);
+ // Verify no socket specified if either local or remote socket address is null.
+ byte[] msgExt = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6,
+ NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
+ byte[] msg;
+ try {
+ msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, remote, AF_INET6,
+ NLM_F_REQUEST);
+ fail("Both remote and local should be null, expected UnknownHostException");
+ } catch (NullPointerException e) {
+ }
+
+ try {
+ msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, local, null, AF_INET6,
+ NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
+ fail("Both remote and local should be null, expected UnknownHostException");
+ } catch (NullPointerException e) {
+ }
+
+ msg = InetDiagMessage.InetDiagReqV2(IPPROTO_TCP, null, null, AF_INET6,
+ NLM_F_REQUEST, 0 /* pad */, 0 /* idiagExt */, TCP_ALL_STATES);
+ assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES, msg);
+ assertArrayEquals(INET_DIAG_REQ_V2_TCP_INET6_NO_ID_SPECIFED_BYTES, msgExt);
+ }
+
// Hexadecimal representation of InetDiagReqV2 request.
private static final String INET_DIAG_MSG_HEX =
// struct nlmsghdr
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index cf3fba8..61f37fd 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -33,6 +33,7 @@
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTP;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_HTTPS;
+import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
@@ -492,6 +493,8 @@
private INetworkMonitor mNetworkMonitor;
private INetworkMonitorCallbacks mNmCallbacks;
private int mNmValidationResult = VALIDATION_RESULT_BASE;
+ private int mProbesCompleted;
+ private int mProbesSucceeded;
private String mNmValidationRedirectUrl = null;
private boolean mNmProvNotificationRequested = false;
@@ -559,6 +562,7 @@
mNmProvNotificationRequested = false;
}
+ mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded);
mNmCallbacks.notifyNetworkTested(
mNmValidationResult, mNmValidationRedirectUrl);
@@ -581,7 +585,7 @@
* @param validated Indicate if network should pretend to be validated.
*/
public void connect(boolean validated) {
- connect(validated, true);
+ connect(validated, true, false /* isStrictMode */);
}
/**
@@ -589,13 +593,13 @@
* @param validated Indicate if network should pretend to be validated.
* @param hasInternet Indicate if network should pretend to have NET_CAPABILITY_INTERNET.
*/
- public void connect(boolean validated, boolean hasInternet) {
+ public void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_INTERNET));
ConnectivityManager.NetworkCallback callback = null;
final ConditionVariable validatedCv = new ConditionVariable();
if (validated) {
- setNetworkValid();
+ setNetworkValid(isStrictMode);
NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(getNetworkCapabilities().getTransportTypes()[0])
.clearCapabilities()
@@ -620,15 +624,15 @@
if (validated) {
// Wait for network to validate.
waitFor(validatedCv);
- setNetworkInvalid();
+ setNetworkInvalid(isStrictMode);
}
if (callback != null) mCm.unregisterNetworkCallback(callback);
}
- public void connectWithCaptivePortal(String redirectUrl) {
- setNetworkPortal(redirectUrl);
- connect(false);
+ public void connectWithCaptivePortal(String redirectUrl, boolean isStrictMode) {
+ setNetworkPortal(redirectUrl, isStrictMode);
+ connect(false, true /* hasInternet */, isStrictMode);
}
public void connectWithPartialConnectivity() {
@@ -636,34 +640,75 @@
connect(false);
}
- public void connectWithPartialValidConnectivity() {
- setNetworkPartialValid();
- connect(false);
+ public void connectWithPartialValidConnectivity(boolean isStrictMode) {
+ setNetworkPartialValid(isStrictMode);
+ connect(false, true /* hasInternet */, isStrictMode);
}
- void setNetworkValid() {
+ void setNetworkValid(boolean isStrictMode) {
mNmValidationResult = VALIDATION_RESULT_VALID;
mNmValidationRedirectUrl = null;
+ int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTP;
+ if (isStrictMode) {
+ probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS;
+ }
+ // The probesCompleted equals to probesSucceeded for the case of valid network, so put
+ // the same value into two different parameter of the method.
+ setProbesStatus(probesSucceeded, probesSucceeded);
}
- void setNetworkInvalid() {
+ void setNetworkInvalid(boolean isStrictMode) {
mNmValidationResult = VALIDATION_RESULT_INVALID;
mNmValidationRedirectUrl = null;
+ int probesCompleted = VALIDATION_RESULT_BASE;
+ int probesSucceeded = VALIDATION_RESULT_INVALID;
+ // If the isStrictMode is true, it means the network is invalid when NetworkMonitor
+ // tried to validate the private DNS but failed.
+ if (isStrictMode) {
+ probesCompleted &= ~NETWORK_VALIDATION_PROBE_HTTP;
+ probesSucceeded = probesCompleted;
+ probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
+ }
+ setProbesStatus(probesCompleted, probesSucceeded);
}
- void setNetworkPortal(String redirectUrl) {
- setNetworkInvalid();
+ void setNetworkPortal(String redirectUrl, boolean isStrictMode) {
+ setNetworkInvalid(isStrictMode);
mNmValidationRedirectUrl = redirectUrl;
+ // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP
+ // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet.
+ int probesCompleted = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
+ int probesSucceeded = VALIDATION_RESULT_INVALID;
+ if (isStrictMode) {
+ probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
+ }
+ setProbesStatus(probesCompleted, probesSucceeded);
}
void setNetworkPartial() {
mNmValidationResult = VALIDATION_RESULT_PARTIAL;
mNmValidationRedirectUrl = null;
+ int probesCompleted = VALIDATION_RESULT_BASE;
+ int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
+ setProbesStatus(probesCompleted, probesSucceeded);
}
- void setNetworkPartialValid() {
- mNmValidationResult = VALIDATION_RESULT_PARTIAL | VALIDATION_RESULT_VALID;
- mNmValidationRedirectUrl = null;
+ void setNetworkPartialValid(boolean isStrictMode) {
+ setNetworkPartial();
+ mNmValidationResult |= VALIDATION_RESULT_VALID;
+ int probesCompleted = VALIDATION_RESULT_BASE;
+ int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS;
+ // Suppose the partial network cannot pass the private DNS validation as well, so only
+ // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded.
+ if (isStrictMode) {
+ probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS;
+ }
+ setProbesStatus(probesCompleted, probesSucceeded);
+ }
+
+ void setProbesStatus(int probesCompleted, int probesSucceeded) {
+ mProbesCompleted = probesCompleted;
+ mProbesSucceeded = probesSucceeded;
}
public String waitForRedirectUrl() {
@@ -2226,7 +2271,7 @@
// With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
// probe.
- mWiFiNetworkAgent.setNetworkPartialValid();
+ mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
// If the user chooses yes to use this partial connectivity wifi, switch the default
// network to wifi and check if wifi becomes valid or not.
mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
@@ -2299,7 +2344,7 @@
callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
- mWiFiNetworkAgent.setNetworkValid();
+ mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
// Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
// validated.
@@ -2317,7 +2362,7 @@
// NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
// valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
// notifyNetworkConnected.
- mWiFiNetworkAgent.connectWithPartialValidConnectivity();
+ mWiFiNetworkAgent.connectWithPartialValidConnectivity(false /* isStrictMode */);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
@@ -2343,7 +2388,7 @@
// Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
String redirectUrl = "http://android.com/path";
- mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl);
+ mWiFiNetworkAgent.connectWithCaptivePortal(redirectUrl, false /* isStrictMode */);
captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), redirectUrl);
@@ -2361,7 +2406,7 @@
mWiFiNetworkAgent);
// Report partial connectivity is accepted.
- mWiFiNetworkAgent.setNetworkPartialValid();
+ mWiFiNetworkAgent.setNetworkPartialValid(false /* isStrictMode */);
mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
false /* always */);
waitForIdle();
@@ -2392,7 +2437,7 @@
// Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
String firstRedirectUrl = "http://example.com/firstPath";
- mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
+ mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), firstRedirectUrl);
@@ -2405,13 +2450,13 @@
// Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
String secondRedirectUrl = "http://example.com/secondPath";
- mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
+ mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl, false /* isStrictMode */);
captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.waitForRedirectUrl(), secondRedirectUrl);
// Make captive portal disappear then revalidate.
// Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
- mWiFiNetworkAgent.setNetworkValid();
+ mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
@@ -2423,7 +2468,7 @@
// Break network connectivity.
// Expect NET_CAPABILITY_VALIDATED onLost callback.
- mWiFiNetworkAgent.setNetworkInvalid();
+ mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
}
@@ -2454,7 +2499,7 @@
mServiceContext.expectNoStartActivityIntent(fastTimeoutMs);
// Turn into a captive portal.
- mWiFiNetworkAgent.setNetworkPortal("http://example.com");
+ mWiFiNetworkAgent.setNetworkPortal("http://example.com", false /* isStrictMode */);
mCm.reportNetworkConnectivity(wifiNetwork, false);
captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
validatedCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
@@ -2475,7 +2520,7 @@
assertEquals(testValue, signInIntent.getStringExtra(testKey));
// Report that the captive portal is dismissed, and check that callbacks are fired
- mWiFiNetworkAgent.setNetworkValid();
+ mWiFiNetworkAgent.setNetworkValid(false /* isStrictMode */);
mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
@@ -2504,7 +2549,7 @@
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
String firstRedirectUrl = "http://example.com/firstPath";
- mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
+ mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl, false /* isStrictMode */);
mWiFiNetworkAgent.expectDisconnected();
mWiFiNetworkAgent.expectPreventReconnectReceived();
@@ -3219,7 +3264,7 @@
Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
// Fail validation on wifi.
- mWiFiNetworkAgent.setNetworkInvalid();
+ mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
mCm.reportNetworkConnectivity(wifiNetwork, false);
defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
@@ -3263,7 +3308,7 @@
wifiNetwork = mWiFiNetworkAgent.getNetwork();
// Fail validation on wifi and expect the dialog to appear.
- mWiFiNetworkAgent.setNetworkInvalid();
+ mWiFiNetworkAgent.setNetworkInvalid(false /* isStrictMode */);
mCm.reportNetworkConnectivity(wifiNetwork, false);
defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
@@ -4299,7 +4344,7 @@
mCm.registerNetworkCallback(request, callback);
// Bring up wifi aware network.
- wifiAware.connect(false, false);
+ wifiAware.connect(false, false, false /* isStrictMode */);
callback.expectAvailableCallbacksUnvalidated(wifiAware);
assertNull(mCm.getActiveNetworkInfo());
@@ -4537,6 +4582,44 @@
}
@Test
+ public void testPrivateDnsNotification() throws Exception {
+ NetworkRequest request = new NetworkRequest.Builder()
+ .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
+ .build();
+ TestNetworkCallback callback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(request, callback);
+ // Bring up wifi.
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(false);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ // Private DNS resolution failed, checking if the notification will be shown or not.
+ mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
+ mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
+ waitForIdle();
+ // If network validation failed, NetworkMonitor will re-evaluate the network.
+ // ConnectivityService should filter the redundant notification. This part is trying to
+ // simulate that situation and check if ConnectivityService could filter that case.
+ mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
+ waitForIdle();
+ verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notifyAsUser(anyString(),
+ eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
+ // If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
+ // shown.
+ mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
+ mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
+ waitForIdle();
+ verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancelAsUser(anyString(),
+ eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), eq(UserHandle.ALL));
+ // If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
+ // shown again.
+ mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
+ mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
+ waitForIdle();
+ verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notifyAsUser(anyString(),
+ eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
+ }
+
+ @Test
public void testPrivateDnsSettingsChange() throws Exception {
// Clear any interactions that occur as a result of CS starting up.
reset(mMockDnsResolver);
@@ -4793,7 +4876,7 @@
// by NetworkMonitor
assertFalse(NetworkMonitorUtils.isValidationRequired(
vpnNetworkAgent.getNetworkCapabilities()));
- vpnNetworkAgent.setNetworkValid();
+ vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
vpnNetworkAgent.connect(false);
mMockVpn.connect();
@@ -4882,7 +4965,8 @@
ranges.add(new UidRange(uid, uid));
mMockVpn.setNetworkAgent(vpnNetworkAgent);
mMockVpn.setUids(ranges);
- vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
+ vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
+ false /* isStrictMode */);
mMockVpn.connect();
defaultCallback.assertNoCallback();
@@ -4913,7 +4997,8 @@
ranges.add(new UidRange(uid, uid));
mMockVpn.setNetworkAgent(vpnNetworkAgent);
mMockVpn.setUids(ranges);
- vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */);
+ vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */,
+ false /* isStrictMode */);
mMockVpn.connect();
defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
@@ -4945,7 +5030,8 @@
ranges.add(new UidRange(uid, uid));
mMockVpn.setNetworkAgent(vpnNetworkAgent);
mMockVpn.setUids(ranges);
- vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */);
+ vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */,
+ false /* isStrictMode */);
mMockVpn.connect();
// Even though the VPN is unvalidated, it becomes the default network for our app.
@@ -4968,7 +5054,7 @@
vpnNetworkAgent.getNetworkCapabilities()));
// Pretend that the VPN network validates.
- vpnNetworkAgent.setNetworkValid();
+ vpnNetworkAgent.setNetworkValid(false /* isStrictMode */);
vpnNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
// Expect to see the validated capability, but no other changes, because the VPN is already
// the default network for the app.
@@ -5000,7 +5086,8 @@
mMockVpn.setNetworkAgent(vpnNetworkAgent);
mMockVpn.connect();
mMockVpn.setUids(ranges);
- vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
+ vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
+ false /* isStrictMode */);
vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());
@@ -5099,7 +5186,8 @@
mMockVpn.setNetworkAgent(vpnNetworkAgent);
mMockVpn.connect();
mMockVpn.setUids(ranges);
- vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */);
+ vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */,
+ false /* isStrictMode */);
vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent);
nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork());