Merge "Add OEM specific error code space which can by used to replace Generic errors." into mm-wireless-dev
diff --git a/api/system-current.txt b/api/system-current.txt
index a8671d4..ca92c45 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -20666,12 +20666,18 @@
}
public class RttManager {
+ method public void disableResponder(android.net.wifi.RttManager.ResponderCallback);
+ method public void enableResponder(android.net.wifi.RttManager.ResponderCallback);
method public deprecated android.net.wifi.RttManager.Capabilities getCapabilities();
method public android.net.wifi.RttManager.RttCapabilities getRttCapabilities();
method public void startRanging(android.net.wifi.RttManager.RttParams[], android.net.wifi.RttManager.RttListener);
method public void stopRanging(android.net.wifi.RttManager.RttListener);
field public static final int BASE = 160256; // 0x27200
field public static final int CMD_OP_ABORTED = 160260; // 0x27204
+ field public static final int CMD_OP_DISABLE_RESPONDER = 160262; // 0x27206
+ field public static final int CMD_OP_ENABLE_RESPONDER = 160261; // 0x27205
+ field public static final int CMD_OP_ENALBE_RESPONDER_FAILED = 160264; // 0x27208
+ field public static final int CMD_OP_ENALBE_RESPONDER_SUCCEEDED = 160263; // 0x27207
field public static final int CMD_OP_FAILED = 160258; // 0x27202
field public static final int CMD_OP_START_RANGING = 160256; // 0x27200
field public static final int CMD_OP_STOP_RANGING = 160257; // 0x27201
@@ -20680,6 +20686,7 @@
field public static final int PREAMBLE_HT = 2; // 0x2
field public static final int PREAMBLE_LEGACY = 1; // 0x1
field public static final int PREAMBLE_VHT = 4; // 0x4
+ field public static final int REASON_INITIATOR_NOT_ALLOWED_WHEN_RESPONDER_ON = -6; // 0xfffffffa
field public static final int REASON_INVALID_LISTENER = -3; // 0xfffffffd
field public static final int REASON_INVALID_REQUEST = -4; // 0xfffffffc
field public static final int REASON_NOT_AVAILABLE = -2; // 0xfffffffe
@@ -20747,6 +20754,25 @@
field public android.net.wifi.RttManager.RttResult[] mResults;
}
+ public static abstract class RttManager.ResponderCallback {
+ ctor public RttManager.ResponderCallback();
+ method public abstract void onResponderEnableFailure(int);
+ method public abstract void onResponderEnabled(android.net.wifi.RttManager.ResponderConfig);
+ }
+
+ public static class RttManager.ResponderConfig implements android.os.Parcelable {
+ ctor public RttManager.ResponderConfig();
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.net.wifi.RttManager.ResponderConfig> CREATOR;
+ field public int centerFreq0;
+ field public int centerFreq1;
+ field public int channelWidth;
+ field public int frequency;
+ field public java.lang.String macAddress;
+ field public int preamble;
+ }
+
public static class RttManager.RttCapabilities implements android.os.Parcelable {
ctor public RttManager.RttCapabilities();
method public int describeContents();
@@ -20756,6 +20782,7 @@
field public boolean lcrSupported;
field public boolean oneSidedRttSupported;
field public int preambleSupported;
+ field public boolean responderSupported;
field public deprecated boolean supportedPeerType;
field public deprecated boolean supportedType;
field public boolean twoSided11McRttSupported;
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index e88bc26..9870e7b 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -20,7 +20,12 @@
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.BackupUtils;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
import java.util.Objects;
/**
@@ -30,6 +35,11 @@
* @hide
*/
public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
+ /**
+ * Current Version of the Backup Serializer.
+ */
+ private static final int BACKUP_VERSION = 1;
+
public static final int CYCLE_NONE = -1;
public static final long WARNING_DISABLED = -1;
public static final long LIMIT_DISABLED = -1;
@@ -191,4 +201,41 @@
return new NetworkPolicy[size];
}
};
+
+ public byte[] getBytesForBackup() throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(baos);
+
+ out.writeInt(BACKUP_VERSION);
+ out.write(template.getBytesForBackup());
+ out.writeInt(cycleDay);
+ BackupUtils.writeString(out, cycleTimezone);
+ out.writeLong(warningBytes);
+ out.writeLong(limitBytes);
+ out.writeLong(lastWarningSnooze);
+ out.writeLong(lastLimitSnooze);
+ out.writeInt(metered ? 1 : 0);
+ out.writeInt(inferred ? 1 : 0);
+ return baos.toByteArray();
+ }
+
+ public static NetworkPolicy getNetworkPolicyFromBackup(DataInputStream in) throws IOException,
+ BackupUtils.BadVersionException {
+ int version = in.readInt();
+ if (version < 1 || version > BACKUP_VERSION) {
+ throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version");
+ }
+
+ NetworkTemplate template = NetworkTemplate.getNetworkTemplateFromBackup(in);
+ int cycleDay = in.readInt();
+ String cycleTimeZone = BackupUtils.readString(in);
+ long warningBytes = in.readLong();
+ long limitBytes = in.readLong();
+ long lastWarningSnooze = in.readLong();
+ long lastLimitSnooze = in.readLong();
+ boolean metered = in.readInt() == 1;
+ boolean inferred = in.readInt() == 1;
+ return new NetworkPolicy(template, cycleDay, cycleTimeZone, warningBytes, limitBytes,
+ lastWarningSnooze, lastLimitSnooze, metered, inferred);
+ }
}
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index b7a411e..5761d66 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -28,15 +28,21 @@
import static android.telephony.TelephonyManager.NETWORK_CLASS_4_G;
import static android.telephony.TelephonyManager.NETWORK_CLASS_UNKNOWN;
import static android.telephony.TelephonyManager.getNetworkClass;
+
import static com.android.internal.util.ArrayUtils.contains;
import android.content.res.Resources;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.BackupUtils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
import java.util.Arrays;
import java.util.Objects;
@@ -47,6 +53,10 @@
* @hide
*/
public class NetworkTemplate implements Parcelable {
+ /**
+ * Current Version of the Backup Serializer.
+ */
+ private static final int BACKUP_VERSION = 1;
public static final int MATCH_MOBILE_ALL = 1;
@Deprecated
@@ -443,4 +453,31 @@
return new NetworkTemplate[size];
}
};
+
+ public byte[] getBytesForBackup() throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(baos);
+
+ out.writeInt(BACKUP_VERSION);
+
+ out.writeInt(mMatchRule);
+ BackupUtils.writeString(out, mSubscriberId);
+ BackupUtils.writeString(out, mNetworkId);
+
+ return baos.toByteArray();
+ }
+
+ public static NetworkTemplate getNetworkTemplateFromBackup(DataInputStream in)
+ throws IOException, BackupUtils.BadVersionException {
+ int version = in.readInt();
+ if (version < 1 || version > BACKUP_VERSION) {
+ throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version");
+ }
+
+ int matchRule = in.readInt();
+ String subscriberId = BackupUtils.readString(in);
+ String networkId = BackupUtils.readString(in);
+
+ return new NetworkTemplate(matchRule, subscriberId, networkId);
+ }
}
diff --git a/core/java/android/util/BackupUtils.java b/core/java/android/util/BackupUtils.java
new file mode 100644
index 0000000..474ceda
--- /dev/null
+++ b/core/java/android/util/BackupUtils.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * Utility methods for Backup/Restore
+ * @hide
+ */
+public class BackupUtils {
+
+ public static final int NULL = 0;
+ public static final int NOT_NULL = 1;
+
+ /**
+ * Thrown when there is a backup version mismatch
+ * between the data received and what the system can handle
+ */
+ public static class BadVersionException extends Exception {
+ public BadVersionException(String message) {
+ super(message);
+ }
+ }
+
+ public static String readString(DataInputStream in) throws IOException {
+ return (in.readByte() == NOT_NULL) ? in.readUTF() : null;
+ }
+
+ public static void writeString(DataOutputStream out, String val) throws IOException {
+ if (val != null) {
+ out.writeByte(NOT_NULL);
+ out.writeUTF(val);
+ } else {
+ out.writeByte(NULL);
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 2e96f18..32df06c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -24,6 +24,8 @@
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
+import android.net.NetworkPolicy;
+import android.net.NetworkPolicyManager;
import android.net.Uri;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
@@ -34,6 +36,7 @@
import android.os.Process;
import android.os.UserHandle;
import android.provider.Settings;
+import android.util.BackupUtils;
import android.util.Log;
import com.android.internal.widget.LockPatternUtils;
@@ -81,36 +84,49 @@
private static final String KEY_GLOBAL = "global";
private static final String KEY_LOCALE = "locale";
private static final String KEY_LOCK_SETTINGS = "lock_settings";
+ private static final String KEY_SOFTAP_CONFIG = "softap_config";
+ private static final String KEY_NETWORK_POLICIES = "network_policies";
// Versioning of the state file. Increment this version
// number any time the set of state items is altered.
- private static final int STATE_VERSION = 4;
+ private static final int STATE_VERSION = 6;
+
+ // Versioning of the Network Policies backup payload.
+ private static final int NETWORK_POLICIES_BACKUP_VERSION = 1;
+
// Slots in the checksum array. Never insert new items in the middle
// of this array; new slots must be appended.
- private static final int STATE_SYSTEM = 0;
- private static final int STATE_SECURE = 1;
- private static final int STATE_LOCALE = 2;
- private static final int STATE_WIFI_SUPPLICANT = 3;
- private static final int STATE_WIFI_CONFIG = 4;
- private static final int STATE_GLOBAL = 5;
- private static final int STATE_LOCK_SETTINGS = 6;
+ private static final int STATE_SYSTEM = 0;
+ private static final int STATE_SECURE = 1;
+ private static final int STATE_LOCALE = 2;
+ private static final int STATE_WIFI_SUPPLICANT = 3;
+ private static final int STATE_WIFI_CONFIG = 4;
+ private static final int STATE_GLOBAL = 5;
+ private static final int STATE_LOCK_SETTINGS = 6;
+ private static final int STATE_SOFTAP_CONFIG = 7;
+ private static final int STATE_NETWORK_POLICIES = 8;
- private static final int STATE_SIZE = 7; // The current number of state items
+ private static final int STATE_SIZE = 9; // The current number of state items
// Number of entries in the checksum array at various version numbers
private static final int STATE_SIZES[] = {
- 0,
- 4, // version 1
- 5, // version 2 added STATE_WIFI_CONFIG
- 6, // version 3 added STATE_GLOBAL
- STATE_SIZE // version 4 added STATE_LOCK_SETTINGS
+ 0,
+ 4, // version 1
+ 5, // version 2 added STATE_WIFI_CONFIG
+ 6, // version 3 added STATE_GLOBAL
+ 7, // version 4 added STATE_LOCK_SETTINGS
+ 8, // version 5 added STATE_SOFTAP_CONFIG
+ STATE_SIZE // version 6 added STATE_NETWORK_POLICIES
};
// Versioning of the 'full backup' format
- private static final int FULL_BACKUP_VERSION = 3;
+ // Increment this version any time a new item is added
+ private static final int FULL_BACKUP_VERSION = 5;
private static final int FULL_BACKUP_ADDED_GLOBAL = 2; // added the "global" entry
private static final int FULL_BACKUP_ADDED_LOCK_SETTINGS = 3; // added the "lock_settings" entry
+ private static final int FULL_BACKUP_ADDED_SOFTAP_CONF = 4; //added the "softap_config" entry
+ private static final int FULL_BACKUP_ADDED_NETWORK_POLICIES = 5; //added "network_policies"
private static final int INTEGER_BYTE_COUNT = Integer.SIZE / Byte.SIZE;
@@ -119,8 +135,8 @@
private static final String TAG = "SettingsBackupAgent";
private static final String[] PROJECTION = {
- Settings.NameValueTable.NAME,
- Settings.NameValueTable.VALUE
+ Settings.NameValueTable.NAME,
+ Settings.NameValueTable.VALUE
};
private static final String FILE_WIFI_SUPPLICANT = "/data/misc/wifi/wpa_supplicant.conf";
@@ -146,7 +162,7 @@
private SettingsHelper mSettingsHelper;
private WifiManager mWfm;
- private static String mWifiConfigFile;
+ private String mWifiConfigFile;
// Chain of asynchronous operations used when rewriting the wifi supplicant config file
WifiDisableRunnable mWifiDisable = null;
@@ -338,7 +354,7 @@
}
continue;
}
- if (! mKnownNetworks.contains(net)) {
+ if (!mKnownNetworks.contains(net)) {
if (DEBUG_BACKUP) {
Log.v(TAG, "Adding " + net.ssid + " / " + net.key_mgmt);
}
@@ -405,26 +421,34 @@
byte[] locale = mSettingsHelper.getLocaleData();
byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
byte[] wifiConfigData = getFileData(mWifiConfigFile);
+ byte[] softApConfigData = getSoftAPConfiguration();
+ byte[] netPoliciesData = getNetworkPolicies();
long[] stateChecksums = readOldChecksums(oldState);
stateChecksums[STATE_SYSTEM] =
- writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data);
+ writeIfChanged(stateChecksums[STATE_SYSTEM], KEY_SYSTEM, systemSettingsData, data);
stateChecksums[STATE_SECURE] =
- writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data);
+ writeIfChanged(stateChecksums[STATE_SECURE], KEY_SECURE, secureSettingsData, data);
stateChecksums[STATE_GLOBAL] =
- writeIfChanged(stateChecksums[STATE_GLOBAL], KEY_GLOBAL, globalSettingsData, data);
+ writeIfChanged(stateChecksums[STATE_GLOBAL], KEY_GLOBAL, globalSettingsData, data);
stateChecksums[STATE_LOCALE] =
- writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data);
+ writeIfChanged(stateChecksums[STATE_LOCALE], KEY_LOCALE, locale, data);
stateChecksums[STATE_WIFI_SUPPLICANT] =
- writeIfChanged(stateChecksums[STATE_WIFI_SUPPLICANT], KEY_WIFI_SUPPLICANT,
- wifiSupplicantData, data);
+ writeIfChanged(stateChecksums[STATE_WIFI_SUPPLICANT], KEY_WIFI_SUPPLICANT,
+ wifiSupplicantData, data);
stateChecksums[STATE_WIFI_CONFIG] =
- writeIfChanged(stateChecksums[STATE_WIFI_CONFIG], KEY_WIFI_CONFIG, wifiConfigData,
- data);
+ writeIfChanged(stateChecksums[STATE_WIFI_CONFIG], KEY_WIFI_CONFIG, wifiConfigData,
+ data);
stateChecksums[STATE_LOCK_SETTINGS] =
- writeIfChanged(stateChecksums[STATE_LOCK_SETTINGS], KEY_LOCK_SETTINGS,
- lockSettingsData, data);
+ writeIfChanged(stateChecksums[STATE_LOCK_SETTINGS], KEY_LOCK_SETTINGS,
+ lockSettingsData, data);
+ stateChecksums[STATE_SOFTAP_CONFIG] =
+ writeIfChanged(stateChecksums[STATE_SOFTAP_CONFIG], KEY_SOFTAP_CONFIG,
+ softApConfigData, data);
+ stateChecksums[STATE_NETWORK_POLICIES] =
+ writeIfChanged(stateChecksums[STATE_NETWORK_POLICIES], KEY_NETWORK_POLICIES,
+ netPoliciesData, data);
writeNewChecksums(stateChecksums, newState);
}
@@ -503,8 +527,8 @@
restoreWifiSupplicant(FILE_WIFI_SUPPLICANT,
restoredSupplicantData, restoredSupplicantData.length);
FileUtils.setPermissions(FILE_WIFI_SUPPLICANT,
- FileUtils.S_IRUSR | FileUtils.S_IWUSR |
- FileUtils.S_IRGRP | FileUtils.S_IWGRP,
+ FileUtils.S_IRUSR | FileUtils.S_IWUSR
+ | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
Process.myUid(), Process.WIFI_UID);
}
if (restoredWifiConfigFile != null) {
@@ -516,8 +540,8 @@
Settings.Global.putInt(getContentResolver(),
Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, scanAlways);
}
- enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED ||
- retainedWifiState == WifiManager.WIFI_STATE_ENABLING);
+ enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED
+ || retainedWifiState == WifiManager.WIFI_STATE_ENABLING);
}
}
}
@@ -542,27 +566,55 @@
while (data.readNextHeader()) {
final String key = data.getKey();
final int size = data.getDataSize();
- if (KEY_SYSTEM.equals(key)) {
- restoreSettings(data, Settings.System.CONTENT_URI, movedToGlobal);
- mSettingsHelper.applyAudioSettings();
- } else if (KEY_SECURE.equals(key)) {
- restoreSettings(data, Settings.Secure.CONTENT_URI, movedToGlobal);
- } else if (KEY_GLOBAL.equals(key)) {
- restoreSettings(data, Settings.Global.CONTENT_URI, null);
- } else if (KEY_WIFI_SUPPLICANT.equals(key)) {
- initWifiRestoreIfNecessary();
- mWifiRestore.incorporateWifiSupplicant(data);
- } else if (KEY_LOCALE.equals(key)) {
- byte[] localeData = new byte[size];
- data.readEntityData(localeData, 0, size);
- mSettingsHelper.setLocaleData(localeData, size);
- } else if (KEY_WIFI_CONFIG.equals(key)) {
- initWifiRestoreIfNecessary();
- mWifiRestore.incorporateWifiConfigFile(data);
- } else if (KEY_LOCK_SETTINGS.equals(key)) {
- restoreLockSettings(data);
- } else {
- data.skipEntityData();
+ switch (key) {
+ case KEY_SYSTEM :
+ restoreSettings(data, Settings.System.CONTENT_URI, movedToGlobal);
+ mSettingsHelper.applyAudioSettings();
+ break;
+
+ case KEY_SECURE :
+ restoreSettings(data, Settings.Secure.CONTENT_URI, movedToGlobal);
+ break;
+
+ case KEY_GLOBAL :
+ restoreSettings(data, Settings.Global.CONTENT_URI, null);
+ break;
+
+ case KEY_WIFI_SUPPLICANT :
+ initWifiRestoreIfNecessary();
+ mWifiRestore.incorporateWifiSupplicant(data);
+ break;
+
+ case KEY_LOCALE :
+ byte[] localeData = new byte[size];
+ data.readEntityData(localeData, 0, size);
+ mSettingsHelper.setLocaleData(localeData, size);
+ break;
+
+ case KEY_WIFI_CONFIG :
+ initWifiRestoreIfNecessary();
+ mWifiRestore.incorporateWifiConfigFile(data);
+ break;
+
+ case KEY_LOCK_SETTINGS :
+ restoreLockSettings(data);
+ break;
+
+ case KEY_SOFTAP_CONFIG :
+ byte[] softapData = new byte[size];
+ data.readEntityData(softapData, 0, size);
+ restoreSoftApConfiguration(softapData);
+ break;
+
+ case KEY_NETWORK_POLICIES:
+ byte[] netPoliciesData = new byte[size];
+ data.readEntityData(netPoliciesData, 0, size);
+ restoreNetworkPolicies(netPoliciesData);
+ break;
+
+ default :
+ data.skipEntityData();
+
}
}
@@ -589,6 +641,8 @@
byte[] locale = mSettingsHelper.getLocaleData();
byte[] wifiSupplicantData = getWifiSupplicant(FILE_WIFI_SUPPLICANT);
byte[] wifiConfigData = getFileData(mWifiConfigFile);
+ byte[] softApConfigData = getSoftAPConfiguration();
+ byte[] netPoliciesData = getNetworkPolicies();
// Write the data to the staging file, then emit that as our tarfile
// representation of the backed-up settings.
@@ -605,16 +659,22 @@
if (DEBUG_BACKUP) Log.d(TAG, systemSettingsData.length + " bytes of settings data");
out.writeInt(systemSettingsData.length);
out.write(systemSettingsData);
- if (DEBUG_BACKUP) Log.d(TAG, secureSettingsData.length + " bytes of secure settings data");
+ if (DEBUG_BACKUP) {
+ Log.d(TAG, secureSettingsData.length + " bytes of secure settings data");
+ }
out.writeInt(secureSettingsData.length);
out.write(secureSettingsData);
- if (DEBUG_BACKUP) Log.d(TAG, globalSettingsData.length + " bytes of global settings data");
+ if (DEBUG_BACKUP) {
+ Log.d(TAG, globalSettingsData.length + " bytes of global settings data");
+ }
out.writeInt(globalSettingsData.length);
out.write(globalSettingsData);
if (DEBUG_BACKUP) Log.d(TAG, locale.length + " bytes of locale data");
out.writeInt(locale.length);
out.write(locale);
- if (DEBUG_BACKUP) Log.d(TAG, wifiSupplicantData.length + " bytes of wifi supplicant data");
+ if (DEBUG_BACKUP) {
+ Log.d(TAG, wifiSupplicantData.length + " bytes of wifi supplicant data");
+ }
out.writeInt(wifiSupplicantData.length);
out.write(wifiSupplicantData);
if (DEBUG_BACKUP) Log.d(TAG, wifiConfigData.length + " bytes of wifi config data");
@@ -623,6 +683,12 @@
if (DEBUG_BACKUP) Log.d(TAG, lockSettingsData.length + " bytes of lock settings data");
out.writeInt(lockSettingsData.length);
out.write(lockSettingsData);
+ if (DEBUG_BACKUP) Log.d(TAG, softApConfigData.length + " bytes of softap config data");
+ out.writeInt(softApConfigData.length);
+ out.write(softApConfigData);
+ if (DEBUG_BACKUP) Log.d(TAG, netPoliciesData.length + " bytes of net policies data");
+ out.writeInt(netPoliciesData.length);
+ out.write(netPoliciesData);
out.flush(); // also flushes downstream
@@ -691,12 +757,12 @@
int retainedWifiState = enableWifi(false);
restoreWifiSupplicant(FILE_WIFI_SUPPLICANT, buffer, nBytes);
FileUtils.setPermissions(FILE_WIFI_SUPPLICANT,
- FileUtils.S_IRUSR | FileUtils.S_IWUSR |
- FileUtils.S_IRGRP | FileUtils.S_IWGRP,
+ FileUtils.S_IRUSR | FileUtils.S_IWUSR
+ | FileUtils.S_IRGRP | FileUtils.S_IWGRP,
Process.myUid(), Process.WIFI_UID);
// retain the previous WIFI state.
- enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED ||
- retainedWifiState == WifiManager.WIFI_STATE_ENABLING);
+ enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED
+ || retainedWifiState == WifiManager.WIFI_STATE_ENABLING);
// wifi config
nBytes = in.readInt();
@@ -714,7 +780,26 @@
restoreLockSettings(buffer, nBytes);
}
}
-
+ // softap config
+ if (version >= FULL_BACKUP_ADDED_SOFTAP_CONF) {
+ nBytes = in.readInt();
+ if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of softap config data");
+ if (nBytes > buffer.length) buffer = new byte[nBytes];
+ if (nBytes > 0) {
+ in.readFully(buffer, 0, nBytes);
+ restoreSoftApConfiguration(buffer);
+ }
+ }
+ // network policies
+ if (version >= FULL_BACKUP_ADDED_NETWORK_POLICIES) {
+ nBytes = in.readInt();
+ if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of network policies data");
+ if (nBytes > buffer.length) buffer = new byte[nBytes];
+ if (nBytes > 0) {
+ in.readFully(buffer, 0, nBytes);
+ restoreNetworkPolicies(buffer);
+ }
+ }
if (DEBUG_BACKUP) Log.d(TAG, "Full restore complete.");
} else {
data.close();
@@ -899,7 +984,7 @@
settingsHelper.restoreValue(this, cr, contentValues, destination, key, value);
if (DEBUG) {
- Log.d(TAG, "Restored setting: " + destination + " : "+ key + "=" + value);
+ Log.d(TAG, "Restored setting: " + destination + " : " + key + "=" + value);
}
}
}
@@ -1031,12 +1116,12 @@
//Will truncate read on a very long file,
//should not happen for a config file
- byte[] bytes = new byte[(int)file.length()];
+ byte[] bytes = new byte[(int) file.length()];
int offset = 0;
int numRead = 0;
while (offset < bytes.length
- && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
+ && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
@@ -1057,7 +1142,6 @@
}
}
}
-
}
private void restoreFileData(String filename, byte[] bytes, int size) {
@@ -1160,6 +1244,87 @@
}
}
+ private byte[] getSoftAPConfiguration() {
+ WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+ try {
+ return wifiManager.getWifiApConfiguration().getBytesForBackup();
+ } catch (IOException ioe) {
+ Log.e(TAG, "Failed to marshal SoftAPConfiguration" + ioe.getMessage());
+ return new byte[0];
+ }
+ }
+
+ private void restoreSoftApConfiguration(byte[] data) {
+ WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+ try {
+ WifiConfiguration config = WifiConfiguration
+ .getWifiConfigFromBackup(new DataInputStream(new ByteArrayInputStream(data)));
+ if (DEBUG) Log.d(TAG, "Successfully unMarshaled WifiConfiguration ");
+ wifiManager.setWifiApConfiguration(config);
+ } catch (IOException | BackupUtils.BadVersionException e) {
+ Log.e(TAG, "Failed to unMarshal SoftAPConfiguration " + e.getMessage());
+ }
+ }
+
+ private byte[] getNetworkPolicies() {
+ NetworkPolicyManager networkPolicyManager =
+ (NetworkPolicyManager) getSystemService(NETWORK_POLICY_SERVICE);
+ NetworkPolicy[] policies = networkPolicyManager.getNetworkPolicies();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ if (policies != null && policies.length != 0) {
+ DataOutputStream out = new DataOutputStream(baos);
+ try {
+ out.writeInt(NETWORK_POLICIES_BACKUP_VERSION);
+ out.writeInt(policies.length);
+ for (NetworkPolicy policy : policies) {
+ if (policy != null) {
+ byte[] marshaledPolicy = policy.getBytesForBackup();
+ out.writeByte(BackupUtils.NOT_NULL);
+ out.writeInt(marshaledPolicy.length);
+ out.write(marshaledPolicy);
+ } else {
+ out.writeByte(BackupUtils.NULL);
+ }
+ }
+ } catch (IOException ioe) {
+ Log.e(TAG, "Failed to convert NetworkPolicies to byte array " + ioe.getMessage());
+ baos.reset();
+ }
+ }
+ return baos.toByteArray();
+ }
+
+ private void restoreNetworkPolicies(byte[] data) {
+ NetworkPolicyManager networkPolicyManager =
+ (NetworkPolicyManager) getSystemService(NETWORK_POLICY_SERVICE);
+ if (data != null && data.length != 0) {
+ DataInputStream in = new DataInputStream(new ByteArrayInputStream(data));
+ try {
+ int version = in.readInt();
+ if (version < 1 || version > NETWORK_POLICIES_BACKUP_VERSION) {
+ throw new BackupUtils.BadVersionException(
+ "Unknown Backup Serialization Version");
+ }
+ int length = in.readInt();
+ NetworkPolicy[] policies = new NetworkPolicy[length];
+ for (int i = 0; i < length; i++) {
+ byte isNull = in.readByte();
+ if (isNull == BackupUtils.NULL) continue;
+ int byteLength = in.readInt();
+ byte[] policyData = new byte[byteLength];
+ in.read(policyData, 0, byteLength);
+ policies[i] = NetworkPolicy.getNetworkPolicyFromBackup(
+ new DataInputStream(new ByteArrayInputStream(policyData)));
+ }
+ // Only set the policies if there was no error in the restore operation
+ networkPolicyManager.setNetworkPolicies(policies);
+ } catch (NullPointerException | IOException | BackupUtils.BadVersionException e) {
+ // NPE can be thrown when trying to instantiate a NetworkPolicy
+ Log.e(TAG, "Failed to convert byte array to NetworkPolicies " + e.getMessage());
+ }
+ }
+ }
+
/**
* Write an int in BigEndian into the byte array.
* @param out byte array
@@ -1181,11 +1346,10 @@
}
private int readInt(byte[] in, int pos) {
- int result =
- ((in[pos ] & 0xFF) << 24) |
- ((in[pos + 1] & 0xFF) << 16) |
- ((in[pos + 2] & 0xFF) << 8) |
- ((in[pos + 3] & 0xFF) << 0);
+ int result = ((in[pos] & 0xFF) << 24)
+ | ((in[pos + 1] & 0xFF) << 16)
+ | ((in[pos + 2] & 0xFF) << 8)
+ | ((in[pos + 3] & 0xFF) << 0);
return result;
}
@@ -1202,4 +1366,4 @@
}
return WifiManager.WIFI_STATE_UNKNOWN;
}
-}
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
index 5fd39c0..dc62609 100644
--- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
+++ b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
@@ -49,7 +49,9 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.Arrays;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Random;
@@ -107,27 +109,33 @@
// so callers can wait for completion.
private final CountDownLatch mCountDownLatch;
- private class Measurement {
+ public class Measurement {
private static final String SUCCEEDED = "SUCCEEDED";
private static final String FAILED = "FAILED";
- // TODO: Refactor to make these private for better encapsulation.
- public String description = "";
- public long startTime;
- public long finishTime;
- public String result = "";
- public Thread thread;
+ private boolean succeeded;
- public void recordSuccess(String msg) {
+ // Package private. TODO: investigate better encapsulation.
+ String description = "";
+ long startTime;
+ long finishTime;
+ String result = "";
+ Thread thread;
+
+ public boolean checkSucceeded() { return succeeded; }
+
+ void recordSuccess(String msg) {
maybeFixupTimes();
+ succeeded = true;
result = SUCCEEDED + ": " + msg;
if (mCountDownLatch != null) {
mCountDownLatch.countDown();
}
}
- public void recordFailure(String msg) {
+ void recordFailure(String msg) {
maybeFixupTimes();
+ succeeded = false;
result = FAILED + ": " + msg;
if (mCountDownLatch != null) {
mCountDownLatch.countDown();
@@ -265,6 +273,51 @@
} catch (InterruptedException ignored) {}
}
+ public List<Measurement> getMeasurements() {
+ // TODO: Consider moving waitForMeasurements() in here to minimize the
+ // chance of caller errors.
+
+ ArrayList<Measurement> measurements = new ArrayList(totalMeasurementCount());
+
+ // Sort measurements IPv4 first.
+ for (Map.Entry<InetAddress, Measurement> entry : mIcmpChecks.entrySet()) {
+ if (entry.getKey() instanceof Inet4Address) {
+ measurements.add(entry.getValue());
+ }
+ }
+ for (Map.Entry<Pair<InetAddress, InetAddress>, Measurement> entry :
+ mExplicitSourceIcmpChecks.entrySet()) {
+ if (entry.getKey().first instanceof Inet4Address) {
+ measurements.add(entry.getValue());
+ }
+ }
+ for (Map.Entry<InetAddress, Measurement> entry : mDnsUdpChecks.entrySet()) {
+ if (entry.getKey() instanceof Inet4Address) {
+ measurements.add(entry.getValue());
+ }
+ }
+
+ // IPv6 measurements second.
+ for (Map.Entry<InetAddress, Measurement> entry : mIcmpChecks.entrySet()) {
+ if (entry.getKey() instanceof Inet6Address) {
+ measurements.add(entry.getValue());
+ }
+ }
+ for (Map.Entry<Pair<InetAddress, InetAddress>, Measurement> entry :
+ mExplicitSourceIcmpChecks.entrySet()) {
+ if (entry.getKey().first instanceof Inet6Address) {
+ measurements.add(entry.getValue());
+ }
+ }
+ for (Map.Entry<InetAddress, Measurement> entry : mDnsUdpChecks.entrySet()) {
+ if (entry.getKey() instanceof Inet6Address) {
+ measurements.add(entry.getValue());
+ }
+ }
+
+ return measurements;
+ }
+
public void dump(IndentingPrintWriter pw) {
pw.println(TAG + ":" + mDescription);
final long unfinished = mCountDownLatch.getCount();
@@ -276,30 +329,13 @@
}
pw.increaseIndent();
- for (Map.Entry<InetAddress, Measurement> entry : mIcmpChecks.entrySet()) {
- if (entry.getKey() instanceof Inet4Address) {
- pw.println(entry.getValue().toString());
- }
+
+ String prefix;
+ for (Measurement m : getMeasurements()) {
+ prefix = m.checkSucceeded() ? "." : "F";
+ pw.println(prefix + " " + m.toString());
}
- for (Map.Entry<InetAddress, Measurement> entry : mIcmpChecks.entrySet()) {
- if (entry.getKey() instanceof Inet6Address) {
- pw.println(entry.getValue().toString());
- }
- }
- for (Map.Entry<Pair<InetAddress, InetAddress>, Measurement> entry :
- mExplicitSourceIcmpChecks.entrySet()) {
- pw.println(entry.getValue().toString());
- }
- for (Map.Entry<InetAddress, Measurement> entry : mDnsUdpChecks.entrySet()) {
- if (entry.getKey() instanceof Inet4Address) {
- pw.println(entry.getValue().toString());
- }
- }
- for (Map.Entry<InetAddress, Measurement> entry : mDnsUdpChecks.entrySet()) {
- if (entry.getKey() instanceof Inet6Address) {
- pw.println(entry.getValue().toString());
- }
- }
+
pw.decreaseIndent();
}
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 06b6ee7..027c325 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -92,13 +92,18 @@
*/
// Implementations must call IpManager#completedPreDhcpAction().
+ // TODO: Remove this requirement, perhaps via some
+ // registerForPreDhcpAction()-style mechanism.
public void onPreDhcpAction() {}
public void onPostDhcpAction() {}
- // TODO: Kill with fire once DHCP and static configuration are moved
- // out of WifiStateMachine.
- public void onIPv4ProvisioningSuccess(DhcpResults dhcpResults) {}
- public void onIPv4ProvisioningFailure() {}
+ // This is purely advisory and not an indication of provisioning
+ // success or failure. This is only here for callers that want to
+ // expose DHCPv4 results to other APIs (e.g., WifiInfo#setInetAddress).
+ // DHCPv4 or static IPv4 configuration failure or success can be
+ // determined by whether or not the passed-in DhcpResults object is
+ // null or not.
+ public void onNewDhcpResults(DhcpResults dhcpResults) {}
public void onProvisioningSuccess(LinkProperties newLp) {}
public void onProvisioningFailure(LinkProperties newLp) {}
@@ -122,6 +127,7 @@
private final Object mLock = new Object();
private final State mStoppedState = new StoppedState();
+ private final State mStoppingState = new StoppingState();
private final State mStartedState = new StartedState();
private final Context mContext;
@@ -179,6 +185,8 @@
// Super simple StateMachine.
addState(mStoppedState);
addState(mStartedState);
+ addState(mStoppingState);
+
setInitialState(mStoppedState);
setLogRecSize(MAX_LOG_RECORDS);
super.start();
@@ -203,13 +211,11 @@
public void startProvisioning(StaticIpConfiguration staticIpConfig) {
getInterfaceIndex();
-
sendMessage(CMD_START, staticIpConfig);
}
public void startProvisioning() {
getInterfaceIndex();
-
sendMessage(CMD_START);
}
@@ -236,6 +242,42 @@
* Internals.
*/
+ @Override
+ protected String getWhatToString(int what) {
+ // TODO: Investigate switching to reflection.
+ switch (what) {
+ case CMD_STOP:
+ return "CMD_STOP";
+ case CMD_START:
+ return "CMD_START";
+ case CMD_CONFIRM:
+ return "CMD_CONFIRM";
+ case EVENT_PRE_DHCP_ACTION_COMPLETE:
+ return "EVENT_PRE_DHCP_ACTION_COMPLETE";
+ case EVENT_NETLINK_LINKPROPERTIES_CHANGED:
+ return "EVENT_NETLINK_LINKPROPERTIES_CHANGED";
+ case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
+ return "DhcpStateMachine.CMD_PRE_DHCP_ACTION";
+ case DhcpStateMachine.CMD_POST_DHCP_ACTION:
+ return "DhcpStateMachine.CMD_POST_DHCP_ACTION";
+ case DhcpStateMachine.CMD_ON_QUIT:
+ return "DhcpStateMachine.CMD_ON_QUIT";
+ }
+ return "UNKNOWN:" + Integer.toString(what);
+ }
+
+ @Override
+ protected String getLogRecString(Message msg) {
+ final String logLine = String.format(
+ "iface{%s/%d} arg1{%d} arg2{%d} obj{%s}",
+ mInterfaceName, mInterfaceIndex,
+ msg.arg1, msg.arg2, Objects.toString(msg.obj));
+ if (VDBG) {
+ Log.d(TAG, getWhatToString(msg.what) + " " + logLine);
+ }
+ return logLine;
+ }
+
private void getInterfaceIndex() {
try {
mInterfaceIndex = NetworkInterface.getByName(mInterfaceName).getIndex();
@@ -260,16 +302,93 @@
}
}
+ // For now: use WifiStateMachine's historical notion of provisioned.
+ private static boolean isProvisioned(LinkProperties lp) {
+ // For historical reasons, we should connect even if all we have is
+ // an IPv4 address and nothing else.
+ return lp.isProvisioned() || lp.hasIPv4Address();
+ }
+
+ // TODO: Investigate folding all this into the existing static function
+ // LinkProperties.compareProvisioning() or some other single function that
+ // takes two LinkProperties objects and returns a ProvisioningChange
+ // object that is a correct and complete assessment of what changed, taking
+ // account of the asymmetries described in the comments in this function.
+ // Then switch to using it everywhere (IpReachabilityMonitor, etc.).
+ private static ProvisioningChange compareProvisioning(
+ LinkProperties oldLp, LinkProperties newLp) {
+ ProvisioningChange delta;
+
+ final boolean wasProvisioned = isProvisioned(oldLp);
+ final boolean isProvisioned = isProvisioned(newLp);
+
+ if (!wasProvisioned && isProvisioned) {
+ delta = ProvisioningChange.GAINED_PROVISIONING;
+ } else if (wasProvisioned && isProvisioned) {
+ delta = ProvisioningChange.STILL_PROVISIONED;
+ } else if (!wasProvisioned && !isProvisioned) {
+ delta = ProvisioningChange.STILL_NOT_PROVISIONED;
+ } else {
+ // (wasProvisioned && !isProvisioned)
+ //
+ // Note that this is true even if we lose a configuration element
+ // (e.g., a default gateway) that would not be required to advance
+ // into provisioned state. This is intended: if we have a default
+ // router and we lose it, that's a sure sign of a problem, but if
+ // we connect to a network with no IPv4 DNS servers, we consider
+ // that to be a network without DNS servers and connect anyway.
+ //
+ // See the comment below.
+ delta = ProvisioningChange.LOST_PROVISIONING;
+ }
+
+ // Additionally:
+ //
+ // Partial configurations (e.g., only an IPv4 address with no DNS
+ // servers and no default route) are accepted as long as DHCPv4
+ // succeeds. On such a network, isProvisioned() will always return
+ // false, because the configuration is not complete, but we want to
+ // connect anyway. It might be a disconnected network such as a
+ // Chromecast or a wireless printer, for example.
+ //
+ // Because on such a network isProvisioned() will always return false,
+ // delta will never be LOST_PROVISIONING. So check for loss of
+ // provisioning here too.
+ if ((oldLp.hasIPv4Address() && !newLp.hasIPv4Address()) ||
+ (oldLp.isIPv6Provisioned() && !newLp.isIPv6Provisioned())) {
+ delta = ProvisioningChange.LOST_PROVISIONING;
+ }
+
+ return delta;
+ }
+
+ private void dispatchCallback(ProvisioningChange delta, LinkProperties newLp) {
+ switch (delta) {
+ case GAINED_PROVISIONING:
+ if (VDBG) { Log.d(TAG, "onProvisioningSuccess()"); }
+ mCallback.onProvisioningSuccess(newLp);
+ break;
+
+ case LOST_PROVISIONING:
+ if (VDBG) { Log.d(TAG, "onProvisioningFailure()"); }
+ mCallback.onProvisioningFailure(newLp);
+ break;
+
+ default:
+ if (VDBG) { Log.d(TAG, "onLinkPropertiesChange()"); }
+ mCallback.onLinkPropertiesChange(newLp);
+ break;
+ }
+ }
+
private ProvisioningChange setLinkProperties(LinkProperties newLp) {
if (mIpReachabilityMonitor != null) {
mIpReachabilityMonitor.updateLinkProperties(newLp);
}
- // TODO: Figure out whether and how to incorporate static configuration
- // into the notion of provisioning.
ProvisioningChange delta;
synchronized (mLock) {
- delta = LinkProperties.compareProvisioning(mLinkProperties, newLp);
+ delta = compareProvisioning(mLinkProperties, newLp);
mLinkProperties = new LinkProperties(newLp);
}
@@ -351,15 +470,45 @@
private void handleIPv4Success(DhcpResults dhcpResults) {
mDhcpResults = new DhcpResults(dhcpResults);
- setLinkProperties(assembleLinkProperties());
- mCallback.onIPv4ProvisioningSuccess(dhcpResults);
+ final LinkProperties newLp = assembleLinkProperties();
+ final ProvisioningChange delta = setLinkProperties(newLp);
+
+ if (VDBG) {
+ Log.d(TAG, "onNewDhcpResults(" + Objects.toString(dhcpResults) + ")");
+ }
+ mCallback.onNewDhcpResults(dhcpResults);
+
+ dispatchCallback(delta, newLp);
}
private void handleIPv4Failure() {
+ // TODO: Figure out to de-dup this and the same code in DhcpClient.
clearIPv4Address();
mDhcpResults = null;
- setLinkProperties(assembleLinkProperties());
- mCallback.onIPv4ProvisioningFailure();
+ final LinkProperties newLp = assembleLinkProperties();
+ ProvisioningChange delta = setLinkProperties(newLp);
+ // If we've gotten here and we're still not provisioned treat that as
+ // a total loss of provisioning.
+ //
+ // Either (a) static IP configuration failed or (b) DHCPv4 failed AND
+ // there was no usable IPv6 obtained before the DHCPv4 timeout.
+ //
+ // Regardless: GAME OVER.
+ //
+ // TODO: Make the DHCP client not time out and just continue in
+ // exponential backoff. Callers such as Wi-Fi which need a timeout
+ // should implement it themselves.
+ if (delta == ProvisioningChange.STILL_NOT_PROVISIONED) {
+ delta = ProvisioningChange.LOST_PROVISIONING;
+ }
+
+ if (VDBG) { Log.d(TAG, "onNewDhcpResults(null)"); }
+ mCallback.onNewDhcpResults(null);
+
+ dispatchCallback(delta, newLp);
+ if (delta == ProvisioningChange.LOST_PROVISIONING) {
+ transitionTo(mStoppingState);
+ }
}
class StoppedState extends State {
@@ -391,13 +540,8 @@
break;
case DhcpStateMachine.CMD_ON_QUIT:
- // CMD_ON_QUIT is really more like "EVENT_ON_QUIT".
- // Shutting down DHCPv4 progresses simultaneously with
- // transitioning to StoppedState, so we can receive this
- // message after we've already transitioned here.
- //
- // TODO: Figure out if this is actually useful and if not
- // expunge it.
+ // Everything is already stopped.
+ Log.e(TAG, "Unexpected CMD_ON_QUIT (already stopped).");
break;
default:
@@ -407,6 +551,30 @@
}
}
+ class StoppingState extends State {
+ @Override
+ public void enter() {
+ if (mDhcpStateMachine == null) {
+ // There's no DHCPv4 for which to wait; proceed to stopped.
+ transitionTo(mStoppedState);
+ }
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case DhcpStateMachine.CMD_ON_QUIT:
+ mDhcpStateMachine = null;
+ transitionTo(mStoppedState);
+ break;
+
+ default:
+ deferMessage(msg);
+ }
+ return HANDLED;
+ }
+ }
+
class StartedState extends State {
@Override
public void enter() {
@@ -439,7 +607,9 @@
if (applyStaticIpConfig()) {
handleIPv4Success(new DhcpResults(mStaticIpConfig));
} else {
- handleIPv4Failure();
+ if (VDBG) { Log.d(TAG, "onProvisioningFailure()"); }
+ mCallback.onProvisioningFailure(getLinkProperties());
+ transitionTo(mStoppingState);
}
} else {
// Start DHCPv4.
@@ -457,7 +627,6 @@
if (mDhcpStateMachine != null) {
mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_STOP_DHCP);
mDhcpStateMachine.doQuit();
- mDhcpStateMachine = null;
}
resetLinkProperties();
@@ -500,28 +669,15 @@
break;
}
final ProvisioningChange delta = setLinkProperties(newLp);
-
- // NOTE: The only receiver of these callbacks currently
- // treats all three of them identically, namely it calls
- // IpManager#getLinkProperties() and makes its own determination.
- switch (delta) {
- case GAINED_PROVISIONING:
- mCallback.onProvisioningSuccess(newLp);
- break;
-
- case LOST_PROVISIONING:
- mCallback.onProvisioningFailure(newLp);
- break;
-
- default:
- // TODO: Only notify on STILL_PROVISIONED?
- mCallback.onLinkPropertiesChange(newLp);
- break;
+ dispatchCallback(delta, newLp);
+ if (delta == ProvisioningChange.LOST_PROVISIONING) {
+ transitionTo(mStoppedState);
}
break;
}
case DhcpStateMachine.CMD_PRE_DHCP_ACTION:
+ if (VDBG) { Log.d(TAG, "onPreDhcpAction()"); }
mCallback.onPreDhcpAction();
break;
@@ -529,6 +685,7 @@
// Note that onPostDhcpAction() is likely to be
// asynchronous, and thus there is no guarantee that we
// will be able to observe any of its effects here.
+ if (VDBG) { Log.d(TAG, "onPostDhcpAction()"); }
mCallback.onPostDhcpAction();
final DhcpResults dhcpResults = (DhcpResults) msg.obj;
@@ -546,11 +703,9 @@
}
case DhcpStateMachine.CMD_ON_QUIT:
- // CMD_ON_QUIT is really more like "EVENT_ON_QUIT".
- // Regardless, we ignore it.
- //
- // TODO: Figure out if this is actually useful and if not
- // expunge it.
+ // DHCPv4 quit early for some reason.
+ Log.e(TAG, "Unexpected CMD_ON_QUIT.");
+ mDhcpStateMachine = null;
break;
default:
diff --git a/wifi/java/android/net/wifi/PasspointManagementObjectDefinition.java b/wifi/java/android/net/wifi/PasspointManagementObjectDefinition.java
index 611ed15..9fc1706 100644
--- a/wifi/java/android/net/wifi/PasspointManagementObjectDefinition.java
+++ b/wifi/java/android/net/wifi/PasspointManagementObjectDefinition.java
@@ -36,15 +36,15 @@
mMoTree = moTree;
}
- public String getmBaseUri() {
+ public String getBaseUri() {
return mBaseUri;
}
- public String getmUrn() {
+ public String getUrn() {
return mUrn;
}
- public String getmMoTree() {
+ public String getMoTree() {
return mMoTree;
}
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index 503e4a2..9137d9d 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -136,6 +136,9 @@
public static final int REASON_INVALID_REQUEST = -4;
/** Do not have required permission */
public static final int REASON_PERMISSION_DENIED = -5;
+ /** Ranging failed because responder role is enabled in STA mode.*/
+ public static final int
+ REASON_INITIATOR_NOT_ALLOWED_WHEN_RESPONDER_ON = -6;
public static final String DESCRIPTION_KEY = "android.net.wifi.RttManager.Description";
@@ -191,6 +194,8 @@
public int preambleSupported;
//RTT bandwidth supported
public int bwSupported;
+ // Whether STA responder role is supported.
+ public boolean responderSupported;
@Override
public String toString() {
@@ -244,6 +249,9 @@
sb.append("is supported.");
+ sb.append(" STA responder role is ")
+ .append(responderSupported ? "supported" : "not supported.");
+
return sb.toString();
}
/** Implement the Parcelable interface {@hide} */
@@ -261,7 +269,7 @@
dest.writeInt(lcrSupported ? 1 : 0);
dest.writeInt(preambleSupported);
dest.writeInt(bwSupported);
-
+ dest.writeInt(responderSupported ? 1 : 0);
}
/** Implement the Parcelable interface {@hide} */
@@ -275,6 +283,7 @@
capabilities.lcrSupported = in.readInt() == 1 ? true : false;
capabilities.preambleSupported = in.readInt();
capabilities.bwSupported = in.readInt();
+ capabilities.responderSupported = (in.readInt() == 1);
return capabilities;
}
/** Implement the Parcelable interface {@hide} */
@@ -898,6 +907,160 @@
sAsyncChannel.sendMessage(CMD_OP_STOP_RANGING, 0, removeListener(listener));
}
+ /**
+ * Callbacks for responder operations.
+ * <p>
+ * A {@link ResponderCallback} is the handle to the calling client. {@link RttManager} will keep
+ * a reference to the callback for the entire period when responder is enabled. The same
+ * callback as used in enabling responder needs to be passed for disabling responder.
+ * The client can freely destroy or reuse the callback after {@link RttManager#disableResponder}
+ * is called.
+ */
+ public abstract static class ResponderCallback {
+ /** Callback when responder is enabled. */
+ public abstract void onResponderEnabled(ResponderConfig config);
+ /** Callback when enabling responder failed. */
+ public abstract void onResponderEnableFailure(int reason);
+ // TODO: consider adding onResponderAborted once it's supported.
+ }
+
+ /**
+ * Enable Wi-Fi RTT responder mode on the device. The enabling result will be delivered via
+ * {@code callback}.
+ * <p>
+ * Note calling this method with the same callback when the responder is already enabled won't
+ * change the responder state, a cached {@link ResponderConfig} from the last enabling will be
+ * returned through the callback.
+ *
+ * @param callback Callback for responder enabling/disabling result.
+ * @throws IllegalArgumentException If {@code callback} is null.
+ */
+ public void enableResponder(ResponderCallback callback) {
+ if (callback == null) {
+ throw new IllegalArgumentException("callback cannot be null");
+ }
+ validateChannel();
+ int key = putListenerIfAbsent(callback);
+ sAsyncChannel.sendMessage(CMD_OP_ENABLE_RESPONDER, 0, key);
+ }
+
+ /**
+ * Disable Wi-Fi RTT responder mode on the device. The {@code callback} needs to be the
+ * same one used in {@link #enableResponder(ResponderCallback)}.
+ * <p>
+ * Calling this method when responder isn't enabled won't have any effect. The callback can be
+ * reused for enabling responder after this method is called.
+ *
+ * @param callback The same callback used for enabling responder.
+ * @throws IllegalArgumentException If {@code callback} is null.
+ */
+ public void disableResponder(ResponderCallback callback) {
+ if (callback == null) {
+ throw new IllegalArgumentException("callback cannot be null");
+ }
+ validateChannel();
+ int key = removeListener(callback);
+ if (key == INVALID_KEY) {
+ Log.e(TAG, "responder not enabled yet");
+ return;
+ }
+ sAsyncChannel.sendMessage(CMD_OP_DISABLE_RESPONDER, 0, key);
+ }
+
+ /**
+ * Configuration used for RTT responder mode. The configuration information can be used by a
+ * peer device to range the responder.
+ *
+ * @see ScanResult
+ */
+ public static class ResponderConfig implements Parcelable {
+
+ // TODO: make all fields final once we can get mac address from responder HAL APIs.
+ /**
+ * Wi-Fi mac address used for responder mode.
+ */
+ public String macAddress = "";
+
+ /**
+ * The primary 20 MHz frequency (in MHz) of the channel where responder is enabled.
+ * @see ScanResult#frequency
+ */
+ public int frequency;
+
+ /**
+ * Center frequency of the channel where responder is enabled on. Only in use when channel
+ * width is at least 40MHz.
+ * @see ScanResult#centerFreq0
+ */
+ public int centerFreq0;
+
+ /**
+ * Center frequency of the second segment when channel width is 80 + 80 MHz.
+ * @see ScanResult#centerFreq1
+ */
+ public int centerFreq1;
+
+ /**
+ * Width of the channel where responder is enabled on.
+ * @see ScanResult#channelWidth
+ */
+ public int channelWidth;
+
+ /**
+ * Preamble supported by responder.
+ */
+ public int preamble;
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("macAddress = ").append(macAddress)
+ .append(" frequency = ").append(frequency)
+ .append(" centerFreq0 = ").append(centerFreq0)
+ .append(" centerFreq1 = ").append(centerFreq1)
+ .append(" channelWidth = ").append(channelWidth)
+ .append(" preamble = ").append(preamble);
+ return builder.toString();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(macAddress);
+ dest.writeInt(frequency);
+ dest.writeInt(centerFreq0);
+ dest.writeInt(centerFreq1);
+ dest.writeInt(channelWidth);
+ dest.writeInt(preamble);
+ }
+
+ /** Implement {@link Parcelable} interface */
+ public static final Parcelable.Creator<ResponderConfig> CREATOR =
+ new Parcelable.Creator<ResponderConfig>() {
+ @Override
+ public ResponderConfig createFromParcel(Parcel in) {
+ ResponderConfig config = new ResponderConfig();
+ config.macAddress = in.readString();
+ config.frequency = in.readInt();
+ config.centerFreq0 = in.readInt();
+ config.centerFreq1 = in.readInt();
+ config.channelWidth = in.readInt();
+ config.preamble = in.readInt();
+ return config;
+ }
+
+ @Override
+ public ResponderConfig[] newArray(int size) {
+ return new ResponderConfig[size];
+ }
+ };
+
+ }
+
/* private methods */
public static final int BASE = Protocol.BASE_WIFI_RTT_MANAGER;
@@ -906,6 +1069,12 @@
public static final int CMD_OP_FAILED = BASE + 2;
public static final int CMD_OP_SUCCEEDED = BASE + 3;
public static final int CMD_OP_ABORTED = BASE + 4;
+ public static final int CMD_OP_ENABLE_RESPONDER = BASE + 5;
+ public static final int CMD_OP_DISABLE_RESPONDER = BASE + 6;
+ public static final int
+ CMD_OP_ENALBE_RESPONDER_SUCCEEDED = BASE + 7;
+ public static final int
+ CMD_OP_ENALBE_RESPONDER_FAILED = BASE + 8;
private Context mContext;
private IRttManager mService;
@@ -992,6 +1161,23 @@
return key;
}
+ // Insert a listener if it doesn't exist in sListenerMap. Returns the key of the listener.
+ private static int putListenerIfAbsent(Object listener) {
+ if (listener == null) return INVALID_KEY;
+ synchronized (sListenerMapLock) {
+ int key = getListenerKey(listener);
+ if (key != INVALID_KEY) {
+ return key;
+ }
+ do {
+ key = sListenerKey++;
+ } while (key == INVALID_KEY);
+ sListenerMap.put(key, listener);
+ return key;
+ }
+
+ }
+
private static Object getListener(int key) {
if (key == INVALID_KEY) return null;
synchronized (sListenerMapLock) {
@@ -1047,9 +1233,9 @@
// to fail and throw an exception
sAsyncChannel = null;
}
- sConnected.countDown();
return;
case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
+ sConnected.countDown();
return;
case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
Log.e(TAG, "Channel connection lost");
@@ -1082,6 +1268,14 @@
((RttListener) listener).onAborted();
removeListener(msg.arg2);
break;
+ case CMD_OP_ENALBE_RESPONDER_SUCCEEDED:
+ ResponderConfig config = (ResponderConfig) msg.obj;
+ ((ResponderCallback) (listener)).onResponderEnabled(config);
+ break;
+ case CMD_OP_ENALBE_RESPONDER_FAILED:
+ ((ResponderCallback) (listener)).onResponderEnableFailure(msg.arg1);
+ removeListener(msg.arg2);
+ break;
default:
if (DBG) Log.d(TAG, "Ignoring message " + msg.what);
return;
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 4a86c59..31da670 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -332,6 +332,7 @@
public static class InformationElement {
public static final int EID_SSID = 0;
public static final int EID_BSS_LOAD = 11;
+ public static final int EID_RSN = 48;
public static final int EID_HT_OPERATION = 61;
public static final int EID_INTERWORKING = 107;
public static final int EID_ROAMING_CONSORTIUM = 111;
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index c8065f9..5d94e53 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -26,7 +26,12 @@
import android.os.Parcelable;
import android.os.UserHandle;
import android.text.TextUtils;
+import android.util.BackupUtils;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
import java.util.Arrays;
import java.util.BitSet;
import java.util.HashMap;
@@ -37,6 +42,10 @@
*/
public class WifiConfiguration implements Parcelable {
private static final String TAG = "WifiConfiguration";
+ /**
+ * Current Version of the Backup Serializer.
+ */
+ private static final int BACKUP_VERSION = 2;
/** {@hide} */
public static final String ssidVarName = "ssid";
/** {@hide} */
@@ -1449,10 +1458,10 @@
if (diff <= 0) {
sbuf.append(" blackListed since <incorrect>");
} else {
- sbuf.append(" blackListed: ").append(Long.toString(diff/1000)).append( "sec ");
+ sbuf.append(" blackListed: ").append(Long.toString(diff / 1000)).append("sec ");
}
}
- if (creatorUid != 0) sbuf.append(" cuid=" + Integer.toString(creatorUid));
+ if (creatorUid != 0) sbuf.append(" cuid=" + creatorUid);
if (creatorName != null) sbuf.append(" cname=" + creatorName);
if (lastUpdateUid != 0) sbuf.append(" luid=" + lastUpdateUid);
if (lastUpdateName != null) sbuf.append(" lname=" + lastUpdateName);
@@ -1467,7 +1476,7 @@
if (diff <= 0) {
sbuf.append("lastConnected since <incorrect>");
} else {
- sbuf.append("lastConnected: ").append(Long.toString(diff/1000)).append( "sec ");
+ sbuf.append("lastConnected: ").append(Long.toString(diff / 1000)).append("sec ");
}
}
if (this.lastConnectionFailure != 0) {
@@ -1476,8 +1485,8 @@
if (diff <= 0) {
sbuf.append("lastConnectionFailure since <incorrect> ");
} else {
- sbuf.append("lastConnectionFailure: ").append(Long.toString(diff/1000));
- sbuf.append( "sec ");
+ sbuf.append("lastConnectionFailure: ").append(Long.toString(diff / 1000));
+ sbuf.append("sec ");
}
}
if (this.lastRoamingFailure != 0) {
@@ -1486,20 +1495,19 @@
if (diff <= 0) {
sbuf.append("lastRoamingFailure since <incorrect> ");
} else {
- sbuf.append("lastRoamingFailure: ").append(Long.toString(diff/1000));
- sbuf.append( "sec ");
+ sbuf.append("lastRoamingFailure: ").append(Long.toString(diff / 1000));
+ sbuf.append("sec ");
}
}
sbuf.append("roamingFailureBlackListTimeMilli: ").
append(Long.toString(this.roamingFailureBlackListTimeMilli));
sbuf.append('\n');
if (this.linkedConfigurations != null) {
- for(String key : this.linkedConfigurations.keySet()) {
+ for (String key : this.linkedConfigurations.keySet()) {
sbuf.append(" linked: ").append(key);
sbuf.append('\n');
}
}
-
sbuf.append("triggeredLow: ").append(this.numUserTriggeredWifiDisableLowRSSI);
sbuf.append(" triggeredBad: ").append(this.numUserTriggeredWifiDisableBadRSSI);
sbuf.append(" triggeredNotHigh: ").append(this.numUserTriggeredWifiDisableNotHighRSSI);
@@ -1989,4 +1997,43 @@
return new WifiConfiguration[size];
}
};
-}
+
+ /**
+ * Serializes the object for backup
+ * @hide
+ */
+ public byte[] getBytesForBackup() throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(baos);
+
+ out.writeInt(BACKUP_VERSION);
+ BackupUtils.writeString(out, SSID);
+ out.writeInt(apBand);
+ out.writeInt(apChannel);
+ BackupUtils.writeString(out, preSharedKey);
+ out.writeInt(getAuthType());
+ return baos.toByteArray();
+ }
+
+ /**
+ * Deserializes a byte array into the WiFiConfiguration Object
+ * @hide
+ */
+ public static WifiConfiguration getWifiConfigFromBackup(DataInputStream in) throws IOException,
+ BackupUtils.BadVersionException {
+ WifiConfiguration config = new WifiConfiguration();
+ int version = in.readInt();
+ if (version < 1 || version > BACKUP_VERSION) {
+ throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version");
+ }
+
+ if (version == 1) return null; // Version 1 is a bad dataset.
+
+ config.SSID = BackupUtils.readString(in);
+ config.apBand = in.readInt();
+ config.apChannel = in.readInt();
+ config.preSharedKey = BackupUtils.readString(in);
+ config.allowedKeyManagement.set(in.readInt());
+ return config;
+ }
+}
\ No newline at end of file
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index d77f2bb..a406fd7 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -101,6 +101,8 @@
/** @hide */
public static final String CA_CERT_KEY = "ca_cert";
/** @hide */
+ public static final String CA_PATH_KEY = "ca_path";
+ /** @hide */
public static final String ENGINE_KEY = "engine";
/** @hide */
public static final String ENGINE_ID_KEY = "engine_id";
@@ -656,6 +658,33 @@
mCaCerts = null;
}
+ /**
+ * Set the ca_path directive on wpa_supplicant.
+ *
+ * From wpa_supplicant documentation:
+ *
+ * Directory path for CA certificate files (PEM). This path may contain
+ * multiple CA certificates in OpenSSL format. Common use for this is to
+ * point to system trusted CA list which is often installed into directory
+ * like /etc/ssl/certs. If configured, these certificates are added to the
+ * list of trusted CAs. ca_cert may also be included in that case, but it is
+ * not required.
+ * @param domain The path for CA certificate files
+ * @hide
+ */
+ public void setCaPath(String path) {
+ setFieldValue(CA_PATH_KEY, path);
+ }
+
+ /**
+ * Get the domain_suffix_match value. See setDomSuffixMatch.
+ * @return The path for CA certificate files.
+ * @hide
+ */
+ public String getCaPath() {
+ return getFieldValue(CA_PATH_KEY, "");
+ }
+
/** Set Client certificate alias.
*
* <p> See the {@link android.security.KeyChain} for details on installing or choosing