Merge "Add new telephony disconnect cause for video calls when tty enabled." into mm-wireless-dev
diff --git a/Android.mk b/Android.mk
index 3bc33bf..9192e96 100644
--- a/Android.mk
+++ b/Android.mk
@@ -406,6 +406,7 @@
telephony/java/com/android/internal/telephony/ISub.aidl \
telephony/java/com/android/internal/telephony/ITelephony.aidl \
telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl \
+ telephony/java/com/android/internal/telephony/ITelephonyDebugSubscriber.aidl \
telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \
telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
wifi/java/android/net/wifi/IWifiManager.aidl \
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 3bd12c0..e27c0fb 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -197,6 +197,19 @@
(1 << NET_CAPABILITY_CAPTIVE_PORTAL);
/**
+ * Network specifier for factories which want to match any network specifier
+ * (NS) in a request. Behavior:
+ * <li>Empty NS in request matches any network factory NS</li>
+ * <li>Empty NS in the network factory NS only matches a request with an
+ * empty NS</li>
+ * <li>"*" (this constant) NS in the network factory matches requests with
+ * any NS</li>
+ *
+ * @hide
+ */
+ public static final String MATCH_ALL_REQUESTS_NETWORK_SPECIFIER = "*";
+
+ /**
* Network capabilities that are not allowed in NetworkRequests. This exists because the
* NetworkFactory / NetworkAgent model does not deal well with the situation where a
* capability's presence cannot be known in advance. If such a capability is requested, then we
@@ -596,7 +609,8 @@
}
private boolean satisfiedBySpecifier(NetworkCapabilities nc) {
return (TextUtils.isEmpty(mNetworkSpecifier) ||
- mNetworkSpecifier.equals(nc.mNetworkSpecifier));
+ mNetworkSpecifier.equals(nc.mNetworkSpecifier) ||
+ MATCH_ALL_REQUESTS_NETWORK_SPECIFIER.equals(nc.mNetworkSpecifier));
}
private boolean equalsSpecifier(NetworkCapabilities nc) {
if (TextUtils.isEmpty(mNetworkSpecifier)) {
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 7da4818..f1edcbe 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -188,6 +188,10 @@
* networks.
*/
public Builder setNetworkSpecifier(String networkSpecifier) {
+ if (NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER.equals(networkSpecifier)) {
+ throw new IllegalArgumentException("Invalid network specifier - must not be '"
+ + NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER + "'");
+ }
mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
return this;
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 327fb8a..9c09f24 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3678,6 +3678,12 @@
throw new IllegalArgumentException("Bad timeout specified");
}
+ if (NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER
+ .equals(networkCapabilities.getNetworkSpecifier())) {
+ throw new IllegalArgumentException("Invalid network specifier - must not be '"
+ + NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER + "'");
+ }
+
NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
nextNetworkRequestId());
NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
new file mode 100644
index 0000000..62c635d
--- /dev/null
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -0,0 +1,483 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.ip;
+
+import android.content.Context;
+import android.net.DhcpResults;
+import android.net.InterfaceConfiguration;
+import android.net.LinkProperties;
+import android.net.LinkProperties.ProvisioningChange;
+import android.net.RouteInfo;
+import android.net.StaticIpConfiguration;
+import android.os.INetworkManagementService;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+import com.android.server.net.NetlinkTracker;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+
+
+/**
+ * IpManager
+ *
+ * This class provides the interface to IP-layer provisioning and maintenance
+ * functionality that can be used by transport layers like Wi-Fi, Ethernet,
+ * et cetera.
+ *
+ * [ Lifetime ]
+ * IpManager is designed to be instantiated as soon as the interface name is
+ * known and can be as long-lived as the class containing it (i.e. declaring
+ * it "private final" is okay).
+ *
+ * @hide
+ */
+public class IpManager extends StateMachine {
+ private static final String TAG = IpManager.class.getSimpleName();
+ private static final boolean DBG = true;
+ private static final boolean VDBG = false;
+
+ /**
+ * Callbacks for both configuration of IpManager and for handling
+ * events as desired.
+ */
+ public static class Callback {
+ /**
+ * Configuration callbacks.
+ *
+ * Override methods as desired in order to control which features
+ * IpManager will use at run time.
+ */
+
+ // An IpReachabilityMonitor will always be started, if only for logging.
+ // This method is checked before probing neighbors and before calling
+ // onProvisioningLost() (see below).
+ public boolean usingIpReachabilityMonitor() {
+ return false;
+ }
+
+ /**
+ * Event callbacks.
+ *
+ * Override methods as desired in order to handle event callbacks
+ * as IpManager invokes them.
+ */
+
+ // TODO: Kill with fire once DHCP and static configuration are moved
+ // out of WifiStateMachine.
+ public void onIPv4ProvisioningSuccess(DhcpResults dhcpResults) {}
+ public void onIPv4ProvisioningFailure() {}
+
+ public void onProvisioningSuccess(LinkProperties newLp) {}
+ public void onProvisioningFailure(LinkProperties newLp) {}
+
+ // Invoked on LinkProperties changes.
+ public void onLinkPropertiesChange(LinkProperties newLp) {}
+
+ // Called when the internal IpReachabilityMonitor (if enabled) has
+ // detected the loss of a critical number of required neighbors.
+ public void onReachabilityLost(String logMsg) {}
+ }
+
+ private static final int CMD_STOP = 1;
+ private static final int CMD_START = 2;
+ private static final int CMD_CONFIRM = 3;
+ private static final int CMD_UPDATE_DHCPV4_RESULTS = 4;
+ // Sent by NetlinkTracker to communicate netlink events.
+ private static final int EVENT_NETLINK_LINKPROPERTIES_CHANGED = 5;
+
+ private static final int MAX_LOG_RECORDS = 1000;
+
+ private final Object mLock = new Object();
+ private final State mStoppedState = new StoppedState();
+ private final State mStartedState = new StartedState();
+
+ private final Context mContext;
+ private final String mInterfaceName;
+ @VisibleForTesting
+ protected final Callback mCallback;
+ private final INetworkManagementService mNwService;
+ private final NetlinkTracker mNetlinkTracker;
+
+ private int mInterfaceIndex;
+
+ /**
+ * Non-final member variables accessed only from within our StateMachine.
+ */
+ private IpReachabilityMonitor mIpReachabilityMonitor;
+ private DhcpResults mDhcpResults;
+ private StaticIpConfiguration mStaticIpConfig;
+
+ /**
+ * Member variables accessed both from within the StateMachine thread
+ * and via accessors from other threads.
+ */
+ @GuardedBy("mLock")
+ private LinkProperties mLinkProperties;
+
+ public IpManager(Context context, String ifName, Callback callback)
+ throws IllegalArgumentException {
+ super(TAG + "." + ifName);
+
+ mContext = context;
+ mInterfaceName = ifName;
+
+ mCallback = callback;
+
+ mNwService = INetworkManagementService.Stub.asInterface(
+ ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
+
+ mNetlinkTracker = new NetlinkTracker(
+ mInterfaceName,
+ new NetlinkTracker.Callback() {
+ @Override
+ public void update() {
+ sendMessage(EVENT_NETLINK_LINKPROPERTIES_CHANGED);
+ }
+ });
+ try {
+ mNwService.registerObserver(mNetlinkTracker);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't register NetlinkTracker: " + e.toString());
+ }
+
+ resetLinkProperties();
+
+ // Super simple StateMachine.
+ addState(mStoppedState);
+ addState(mStartedState);
+ setInitialState(mStoppedState);
+ setLogRecSize(MAX_LOG_RECORDS);
+ super.start();
+ }
+
+ /**
+ * A special constructor for use in testing that bypasses some of the more
+ * complicated setup bits.
+ *
+ * TODO: Figure out how to delete this yet preserve testability.
+ */
+ @VisibleForTesting
+ protected IpManager(String ifName, Callback callback) {
+ super(TAG + ".test-" + ifName);
+ mInterfaceName = ifName;
+ mCallback = callback;
+
+ mContext = null;
+ mNwService = null;
+ mNetlinkTracker = null;
+ }
+
+ public void startProvisioning(StaticIpConfiguration staticIpConfig) {
+ getInterfaceIndex();
+
+ sendMessage(CMD_START, staticIpConfig);
+ }
+
+ public void startProvisioning() {
+ getInterfaceIndex();
+
+ sendMessage(CMD_START);
+ }
+
+ public void stop() {
+ sendMessage(CMD_STOP);
+ }
+
+ public void confirmConfiguration() {
+ sendMessage(CMD_CONFIRM);
+ }
+
+ public LinkProperties getLinkProperties() {
+ synchronized (mLock) {
+ return new LinkProperties(mLinkProperties);
+ }
+ }
+
+ // TODO: Kill with fire once DHCPv4/static config is moved into IpManager.
+ public void updateWithDhcpResults(DhcpResults dhcpResults) {
+ sendMessage(CMD_UPDATE_DHCPV4_RESULTS, dhcpResults);
+ }
+
+
+ /**
+ * Internals.
+ */
+
+ private void getInterfaceIndex() {
+ try {
+ mInterfaceIndex = NetworkInterface.getByName(mInterfaceName).getIndex();
+ } catch (SocketException | NullPointerException e) {
+ // TODO: throw new IllegalStateException.
+ Log.e(TAG, "ALERT: Failed to get interface index: ", e);
+ }
+ }
+
+ // This needs to be called with care to ensure that our LinkProperties
+ // are in sync with the actual LinkProperties of the interface. For example,
+ // we should only call this if we know for sure that there are no IP addresses
+ // assigned to the interface, etc.
+ private void resetLinkProperties() {
+ mNetlinkTracker.clearLinkProperties();
+ mDhcpResults = null;
+ mStaticIpConfig = null;
+
+ synchronized (mLock) {
+ mLinkProperties = new LinkProperties();
+ mLinkProperties.setInterfaceName(mInterfaceName);
+ }
+ }
+
+ 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);
+ mLinkProperties = new LinkProperties(newLp);
+ }
+
+ if (DBG) {
+ switch (delta) {
+ case GAINED_PROVISIONING:
+ case LOST_PROVISIONING:
+ Log.d(TAG, "provisioning: " + delta);
+ break;
+ }
+ }
+
+ return delta;
+ }
+
+ private LinkProperties assembleLinkProperties() {
+ // [1] Create a new LinkProperties object to populate.
+ LinkProperties newLp = new LinkProperties();
+ newLp.setInterfaceName(mInterfaceName);
+
+ // [2] Pull in data from netlink:
+ // - IPv4 addresses
+ // - IPv6 addresses
+ // - IPv6 routes
+ // - IPv6 DNS servers
+ LinkProperties netlinkLinkProperties = mNetlinkTracker.getLinkProperties();
+ newLp.setLinkAddresses(netlinkLinkProperties.getLinkAddresses());
+ for (RouteInfo route : netlinkLinkProperties.getRoutes()) {
+ newLp.addRoute(route);
+ }
+ for (InetAddress dns : netlinkLinkProperties.getDnsServers()) {
+ // Only add likely reachable DNS servers.
+ // TODO: investigate deleting this.
+ if (newLp.isReachable(dns)) {
+ newLp.addDnsServer(dns);
+ }
+ }
+
+ // [3] Add in data from DHCPv4, if available.
+ //
+ // mDhcpResults is never shared with any other owner so we don't have
+ // to worry about concurrent modification.
+ if (mDhcpResults != null) {
+ for (RouteInfo route : mDhcpResults.getRoutes(mInterfaceName)) {
+ newLp.addRoute(route);
+ }
+ for (InetAddress dns : mDhcpResults.dnsServers) {
+ // Only add likely reachable DNS servers.
+ // TODO: investigate deleting this.
+ if (newLp.isReachable(dns)) {
+ newLp.addDnsServer(dns);
+ }
+ }
+ newLp.setDomains(mDhcpResults.domains);
+ }
+
+ if (VDBG) {
+ Log.d(TAG, "newLp{" + newLp + "}");
+ }
+
+ return newLp;
+ }
+
+ class StoppedState extends State {
+ @Override
+ public void enter() {
+ try {
+ mNwService.disableIpv6(mInterfaceName);
+ mNwService.clearInterfaceAddresses(mInterfaceName);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to clear addresses or disable IPv6" + e);
+ }
+
+ resetLinkProperties();
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_STOP:
+ break;
+
+ case CMD_START:
+ mStaticIpConfig = (StaticIpConfiguration) msg.obj;
+ transitionTo(mStartedState);
+ break;
+
+ case EVENT_NETLINK_LINKPROPERTIES_CHANGED:
+ setLinkProperties(assembleLinkProperties());
+ break;
+
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
+ }
+ }
+
+ class StartedState extends State {
+ @Override
+ public void enter() {
+ // Set privacy extensions.
+ try {
+ mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
+ mNwService.enableIpv6(mInterfaceName);
+ } catch (RemoteException re) {
+ Log.e(TAG, "Unable to change interface settings: " + re);
+ } catch (IllegalStateException ie) {
+ Log.e(TAG, "Unable to change interface settings: " + ie);
+ }
+
+ mIpReachabilityMonitor = new IpReachabilityMonitor(
+ mContext,
+ mInterfaceName,
+ new IpReachabilityMonitor.Callback() {
+ @Override
+ public void notifyLost(InetAddress ip, String logMsg) {
+ if (mCallback.usingIpReachabilityMonitor()) {
+ mCallback.onReachabilityLost(logMsg);
+ }
+ }
+ });
+
+ // If we have a StaticIpConfiguration attempt to apply it and
+ // handle the result accordingly.
+ if (mStaticIpConfig != null) {
+ if (applyStaticIpConfig()) {
+ sendMessage(CMD_UPDATE_DHCPV4_RESULTS, new DhcpResults(mStaticIpConfig));
+ } else {
+ sendMessage(CMD_UPDATE_DHCPV4_RESULTS);
+ }
+ }
+ }
+
+ @Override
+ public void exit() {
+ mIpReachabilityMonitor.stop();
+ mIpReachabilityMonitor = null;
+
+ resetLinkProperties();
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_STOP:
+ transitionTo(mStoppedState);
+ break;
+
+ case CMD_START:
+ // TODO: Defer this message to be delivered after a state transition
+ // to StoppedState. That way, receiving CMD_START in StartedState
+ // effects a restart.
+ Log.e(TAG, "ALERT: START received in StartedState.");
+ break;
+
+ case CMD_CONFIRM:
+ if (mCallback.usingIpReachabilityMonitor()) {
+ mIpReachabilityMonitor.probeAll();
+ }
+ break;
+
+ case CMD_UPDATE_DHCPV4_RESULTS:
+ final DhcpResults dhcpResults = (DhcpResults) msg.obj;
+ if (dhcpResults != null) {
+ mDhcpResults = new DhcpResults(dhcpResults);
+ setLinkProperties(assembleLinkProperties());
+ mCallback.onIPv4ProvisioningSuccess(dhcpResults);
+ } else {
+ mDhcpResults = null;
+ setLinkProperties(assembleLinkProperties());
+ mCallback.onIPv4ProvisioningFailure();
+ }
+ break;
+
+ case EVENT_NETLINK_LINKPROPERTIES_CHANGED:
+ final LinkProperties newLp = assembleLinkProperties();
+ 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;
+ }
+
+ break;
+
+ default:
+ return NOT_HANDLED;
+ }
+ return HANDLED;
+ }
+
+ private boolean applyStaticIpConfig() {
+ final InterfaceConfiguration ifcg = new InterfaceConfiguration();
+ ifcg.setLinkAddress(mStaticIpConfig.ipAddress);
+ ifcg.setInterfaceUp();
+ try {
+ mNwService.setInterfaceConfig(mInterfaceName, ifcg);
+ if (DBG) Log.d(TAG, "Static IP configuration succeeded");
+ } catch (IllegalStateException | RemoteException e) {
+ Log.e(TAG, "Static IP configuration failed: ", e);
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 97e16da..d096c28 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -52,13 +52,16 @@
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.IBinder;
import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
+import android.os.Messenger;
import android.os.MessageQueue.IdleHandler;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import android.util.LogPrinter;
@@ -1291,6 +1294,36 @@
validatedCallback.expectCallback(CallbackState.LOST);
}
+ @SmallTest
+ public void testInvalidNetworkSpecifier() {
+ boolean execptionCalled = true;
+
+ try {
+ NetworkRequest.Builder builder = new NetworkRequest.Builder();
+ builder.setNetworkSpecifier(MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
+ execptionCalled = false;
+ } catch (IllegalArgumentException e) {
+ // do nothing - should get here
+ }
+
+ assertTrue("NetworkReqeuest builder with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
+ execptionCalled);
+
+ try {
+ NetworkCapabilities networkCapabilities = new NetworkCapabilities();
+ networkCapabilities.addTransportType(TRANSPORT_WIFI)
+ .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
+ mService.requestNetwork(networkCapabilities, null, 0, null,
+ ConnectivityManager.TYPE_WIFI);
+ execptionCalled = false;
+ } catch (IllegalArgumentException e) {
+ // do nothing - should get here
+ }
+
+ assertTrue("ConnectivityService requestNetwork with MATCH_ALL_REQUESTS_NETWORK_SPECIFIER",
+ execptionCalled);
+ }
+
private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
index ea96e7c..6425744 100644
--- a/telephony/java/android/telephony/ModemActivityInfo.java
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -48,7 +48,9 @@
mTimestamp = timestamp;
mSleepTimeMs = sleepTimeMs;
mIdleTimeMs = idleTimeMs;
- System.arraycopy(txTimeMs, 0, mTxTimeMs, 0, Math.min(txTimeMs.length, TX_POWER_LEVELS));
+ if (txTimeMs != null) {
+ System.arraycopy(txTimeMs, 0, mTxTimeMs, 0, Math.min(txTimeMs.length, TX_POWER_LEVELS));
+ }
mRxTimeMs = rxTimeMs;
mEnergyUsed = energyUsed;
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl b/telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl
index 5dffa28..069fcbf 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl
@@ -16,8 +16,9 @@
package com.android.internal.telephony;
-import android.os.Bundle;
+import com.android.internal.telephony.ITelephonyDebugSubscriber;
+import android.os.Bundle;
/**
* Interface used to interact with the Telephony debug service.
@@ -36,4 +37,7 @@
* @param data optional
*/
void writeEvent(long timestamp, int phoneId, int tag, int param1, int param2, in Bundle data);
+
+ void subscribe(in ITelephonyDebugSubscriber subscriber);
+ void unsubscribe(in ITelephonyDebugSubscriber subscriber);
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyDebugSubscriber.aidl b/telephony/java/com/android/internal/telephony/ITelephonyDebugSubscriber.aidl
new file mode 100644
index 0000000..64eb0f1
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/ITelephonyDebugSubscriber.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import com.android.internal.telephony.TelephonyEvent;
+
+import android.os.Bundle;
+
+/**
+ * Interface used to subscribe for events from Telephony debug service.
+ *
+ * {@hide}
+ */
+oneway interface ITelephonyDebugSubscriber {
+
+ /**
+ * Called when Telephony debug service has events.
+ */
+ void onEvents(in TelephonyEvent[] events);
+}
diff --git a/telephony/java/com/android/internal/telephony/TelephonyEvent.aidl b/telephony/java/com/android/internal/telephony/TelephonyEvent.aidl
new file mode 100644
index 0000000..1e74b31
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/TelephonyEvent.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+parcelable TelephonyEvent;
diff --git a/telephony/java/com/android/internal/telephony/TelephonyEvent.java b/telephony/java/com/android/internal/telephony/TelephonyEvent.java
new file mode 100644
index 0000000..26d466d
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/TelephonyEvent.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A parcelable used in ITelephonyDebugSubscriber.aidl
+ */
+public class TelephonyEvent implements Parcelable {
+
+ final public long timestamp;
+ final public int phoneId;
+ final public int tag;
+ final public int param1;
+ final public int param2;
+ final public Bundle data;
+
+ public TelephonyEvent(long timestamp, int phoneId, int tag,
+ int param1, int param2, Bundle data) {
+ this.timestamp = timestamp;
+ this.phoneId = phoneId;
+ this.tag = tag;
+ this.param1 = param1;
+ this.param2 = param2;
+ this.data = data;
+ }
+
+ /** Implement the Parcelable interface */
+ public static final Parcelable.Creator<TelephonyEvent> CREATOR
+ = new Parcelable.Creator<TelephonyEvent> (){
+ public TelephonyEvent createFromParcel(Parcel source) {
+ final long timestamp = source.readLong();
+ final int phoneId = source.readInt();
+ final int tag = source.readInt();
+ final int param1 = source.readInt();
+ final int param2 = source.readInt();
+ final Bundle data = source.readBundle();
+ return new TelephonyEvent(timestamp, phoneId, tag, param1, param2, data);
+ }
+
+ public TelephonyEvent[] newArray(int size) {
+ return new TelephonyEvent[size];
+ }
+ };
+
+ /** Implement the Parcelable interface */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(timestamp);
+ dest.writeInt(phoneId);
+ dest.writeInt(tag);
+ dest.writeInt(param1);
+ dest.writeInt(param2);
+ dest.writeBundle(data);
+ }
+
+ public String toString() {
+ return String.format("%d,%d,%d,%d,%d,%s",
+ timestamp, phoneId, tag, param1, param2, data);
+ }
+}
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index dc06789..1f05339 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -18,7 +18,9 @@
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
/**
* Describes information about a detected access point. In addition
@@ -301,6 +303,12 @@
/**
* @hide
+ * anqp lines from supplicant BSS response
+ */
+ public List<String> anqpLines;
+
+ /**
+ * @hide
* storing the raw bytes of full result IEs
**/
public byte[] bytes;
@@ -518,6 +526,15 @@
} else {
dest.writeInt(0);
}
+
+ if (anqpLines != null) {
+ dest.writeInt(anqpLines.size());
+ for (int i = 0; i < anqpLines.size(); i++) {
+ dest.writeString(anqpLines.get(i));
+ }
+ } else {
+ dest.writeInt(0);
+ }
}
/** Implement the Parcelable interface {@hide} */
@@ -565,6 +582,14 @@
in.readByteArray(sr.informationElements[i].bytes);
}
}
+
+ n = in.readInt();
+ if (n != 0) {
+ sr.anqpLines = new ArrayList<String>();
+ for (int i = 0; i < n; i++) {
+ sr.anqpLines.add(in.readString());
+ }
+ }
return sr;
}
diff --git a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl b/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
index ff3d29f..ec9e462 100644
--- a/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
+++ b/wifi/java/android/net/wifi/nan/IWifiNanManager.aidl
@@ -43,7 +43,8 @@
void publish(int sessionId, in PublishData publishData, in PublishSettings publishSettings);
void subscribe(int sessionId, in SubscribeData subscribeData,
in SubscribeSettings subscribeSettings);
- void sendMessage(int sessionId, int peerId, in byte[] message, int messageLength);
+ void sendMessage(int sessionId, int peerId, in byte[] message, int messageLength,
+ int messageId);
void stopSession(int sessionId);
void destroySession(int sessionId);
}
diff --git a/wifi/java/android/net/wifi/nan/IWifiNanSessionListener.aidl b/wifi/java/android/net/wifi/nan/IWifiNanSessionListener.aidl
index 773f83b..50c34d9 100644
--- a/wifi/java/android/net/wifi/nan/IWifiNanSessionListener.aidl
+++ b/wifi/java/android/net/wifi/nan/IWifiNanSessionListener.aidl
@@ -32,7 +32,7 @@
void onMatch(int peerId, in byte[] serviceSpecificInfo,
int serviceSpecificInfoLength, in byte[] matchFilter, int matchFilterLength);
- void onMessageSendSuccess();
- void onMessageSendFail(int reason);
+ void onMessageSendSuccess(int messageId);
+ void onMessageSendFail(int messageId, int reason);
void onMessageReceived(int peerId, in byte[] message, int messageLength);
}
diff --git a/wifi/java/android/net/wifi/nan/WifiNanManager.java b/wifi/java/android/net/wifi/nan/WifiNanManager.java
index 877f993..cb82268 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanManager.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanManager.java
@@ -319,13 +319,14 @@
/**
* {@hide}
*/
- public void sendMessage(int sessionId, int peerId, byte[] message, int messageLength) {
+ public void sendMessage(int sessionId, int peerId, byte[] message, int messageLength,
+ int messageId) {
try {
if (VDBG) {
Log.v(TAG, "sendMessage(): sessionId=" + sessionId + ", peerId=" + peerId
- + ", messageLength=" + messageLength);
+ + ", messageLength=" + messageLength + ", messageId=" + messageId);
}
- mService.sendMessage(sessionId, peerId, message, messageLength);
+ mService.sendMessage(sessionId, peerId, message, messageLength, messageId);
} catch (RemoteException e) {
Log.w(TAG, "subscribe RemoteException (FYI - ignoring): " + e);
}
diff --git a/wifi/java/android/net/wifi/nan/WifiNanSession.java b/wifi/java/android/net/wifi/nan/WifiNanSession.java
index c6b384e..d0a9410 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanSession.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanSession.java
@@ -103,8 +103,11 @@
* @param message The message to be transmitted.
* @param messageLength The number of bytes from the {@code message} to be
* transmitted.
+ * @param messageId An arbitrary integer used by the caller to identify the
+ * message. The same integer ID will be returned in the callbacks
+ * indicated message send success or failure.
*/
- public void sendMessage(int peerId, byte[] message, int messageLength) {
- mManager.sendMessage(mSessionId, peerId, message, messageLength);
+ public void sendMessage(int peerId, byte[] message, int messageLength, int messageId) {
+ mManager.sendMessage(mSessionId, peerId, message, messageLength, messageId);
}
}
diff --git a/wifi/java/android/net/wifi/nan/WifiNanSessionListener.java b/wifi/java/android/net/wifi/nan/WifiNanSessionListener.java
index c9d08c7..d5e59f0 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanSessionListener.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanSessionListener.java
@@ -210,10 +210,10 @@
msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE2), msg.arg2);
break;
case LISTEN_MESSAGE_SEND_SUCCESS:
- WifiNanSessionListener.this.onMessageSendSuccess();
+ WifiNanSessionListener.this.onMessageSendSuccess(msg.arg1);
break;
case LISTEN_MESSAGE_SEND_FAIL:
- WifiNanSessionListener.this.onMessageSendFail(msg.arg1);
+ WifiNanSessionListener.this.onMessageSendFail(msg.arg1, msg.arg2);
break;
case LISTEN_MESSAGE_RECEIVED:
WifiNanSessionListener.this.onMessageReceived(msg.arg2,
@@ -306,7 +306,7 @@
* {@link WifiNanSessionListener#onMessageSendFail(int)} will be received -
* never both.
*/
- public void onMessageSendSuccess() {
+ public void onMessageSendSuccess(int messageId) {
if (VDBG) Log.v(TAG, "onMessageSendSuccess: called in stub - override if interested");
}
@@ -325,7 +325,7 @@
* @param reason The failure reason using {@code NanSessionListener.FAIL_*}
* codes.
*/
- public void onMessageSendFail(int reason) {
+ public void onMessageSendFail(int messageId, int reason) {
if (VDBG) Log.v(TAG, "onMessageSendFail: called in stub - override if interested");
}
@@ -401,19 +401,21 @@
}
@Override
- public void onMessageSendSuccess() {
+ public void onMessageSendSuccess(int messageId) {
if (VDBG) Log.v(TAG, "onMessageSendSuccess");
Message msg = mHandler.obtainMessage(LISTEN_MESSAGE_SEND_SUCCESS);
+ msg.arg1 = messageId;
mHandler.sendMessage(msg);
}
@Override
- public void onMessageSendFail(int reason) {
+ public void onMessageSendFail(int messageId, int reason) {
if (VDBG) Log.v(TAG, "onMessageSendFail: reason=" + reason);
Message msg = mHandler.obtainMessage(LISTEN_MESSAGE_SEND_FAIL);
- msg.arg1 = reason;
+ msg.arg1 = messageId;
+ msg.arg2 = reason;
mHandler.sendMessage(msg);
}