Merge "Update generate_api_reference_md.py to work with Python 3" am: 47de3cf5e3
Original change: https://android-review.googlesource.com/c/platform/external/sl4a/+/1826966
Change-Id: If9b84f4bd56e7bd5d92a2b9e1ecf6c04650a0bd4
diff --git a/Common/Android.bp b/Common/Android.bp
index 3898b24..ad42d29 100644
--- a/Common/Android.bp
+++ b/Common/Android.bp
@@ -32,11 +32,13 @@
"android-common",
"sl4a.Utils",
"junit",
+ "modules-utils-build",
],
sdk_version: "core_platform",
libs: [
"framework-wifi.impl", // allow SL4A to access @hide Wifi APIs
+ "framework-connectivity.impl",
"framework",
"telephony-common",
diff --git a/Common/src/com/googlecode/android_scripting/facade/AndroidFacade.java b/Common/src/com/googlecode/android_scripting/facade/AndroidFacade.java
index 79ed163..1689c88 100644
--- a/Common/src/com/googlecode/android_scripting/facade/AndroidFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/AndroidFacade.java
@@ -44,6 +44,8 @@
import android.widget.EditText;
import android.widget.Toast;
+import com.android.modules.utils.build.SdkLevel;
+
import com.googlecode.android_scripting.BaseApplication;
import com.googlecode.android_scripting.FileUtils;
import com.googlecode.android_scripting.FutureActivityTaskExecutor;
@@ -600,6 +602,16 @@
return Build.VERSION.SDK_INT;
}
+ @Rpc(description = "Returns whether the device is running SDK at least R")
+ public boolean isSdkAtLeastR() {
+ return SdkLevel.isAtLeastR();
+ }
+
+ @Rpc(description = "Returns whether the device is running SDK at least S")
+ public boolean isSdkAtLeastS() {
+ return SdkLevel.isAtLeastS();
+ }
+
@Rpc(description = "Returns the current device time.")
public Long getBuildTime() {
return Build.TIME;
diff --git a/Common/src/com/googlecode/android_scripting/facade/ConnectivityConstants.java b/Common/src/com/googlecode/android_scripting/facade/ConnectivityConstants.java
index c46a3a1..867f624 100644
--- a/Common/src/com/googlecode/android_scripting/facade/ConnectivityConstants.java
+++ b/Common/src/com/googlecode/android_scripting/facade/ConnectivityConstants.java
@@ -89,4 +89,10 @@
public static final String PrivateDnsModeOff = "off";
public static final String PrivateDnsModeOpportunistic = "opportunistic";
public static final String PrivateDnsModeStrict = "hostname";
+
+ /**
+ * Constants for NetworkCapabilties/NetworkRequest
+ */
+ public static final String NET_CAPABILITIES_TRANSPORT_TYPE = "TransportType";
+ public static final String NET_CAPABILITIES_CAPABILITIES = "Capability";
}
diff --git a/Common/src/com/googlecode/android_scripting/facade/ConnectivityEvents.java b/Common/src/com/googlecode/android_scripting/facade/ConnectivityEvents.java
index ec9834a..64c6e65 100644
--- a/Common/src/com/googlecode/android_scripting/facade/ConnectivityEvents.java
+++ b/Common/src/com/googlecode/android_scripting/facade/ConnectivityEvents.java
@@ -17,8 +17,8 @@
package com.googlecode.android_scripting.facade;
import android.net.NetworkCapabilities;
-import android.net.wifi.aware.WifiAwareNetworkInfo;
+import com.googlecode.android_scripting.jsonrpc.JsonBuilder;
import com.googlecode.android_scripting.jsonrpc.JsonSerializable;
import org.json.JSONException;
@@ -136,33 +136,7 @@
*/
public JSONObject toJSON() throws JSONException {
JSONObject json = super.toJSON();
- json.put(ConnectivityConstants.NetworkCallbackContainer.RSSI,
- mNetworkCapabilities.getSignalStrength());
-
- json.put(ConnectivityConstants.NetworkCallbackContainer.METERED,
- !mNetworkCapabilities.hasCapability(ConnectivityConstants.NET_CAPABILITY_TEMPORARILY_NOT_METERED));
-
- if (mNetworkCapabilities.getNetworkSpecifier() != null) {
- json.put("network_specifier",
- mNetworkCapabilities.getNetworkSpecifier().toString());
- }
- if (mNetworkCapabilities.getTransportInfo() instanceof WifiAwareNetworkInfo) {
- WifiAwareNetworkInfo anc =
- (WifiAwareNetworkInfo) mNetworkCapabilities.getTransportInfo();
-
- String ipv6 = anc.getPeerIpv6Addr().toString();
- if (ipv6.charAt(0) == '/') {
- ipv6 = ipv6.substring(1);
- }
- json.put("aware_ipv6", ipv6);
- if (anc.getPort() != 0) {
- json.put("aware_port", anc.getPort());
- }
- if (anc.getTransportProtocol() != -1) {
- json.put("aware_transport_protocol", anc.getTransportProtocol());
- }
- }
- return json;
+ return JsonBuilder.buildNetworkCapabilities(json, mNetworkCapabilities);
}
}
diff --git a/Common/src/com/googlecode/android_scripting/facade/ConnectivityManagerFacade.java b/Common/src/com/googlecode/android_scripting/facade/ConnectivityManagerFacade.java
index 9040b83..26f0012 100644
--- a/Common/src/com/googlecode/android_scripting/facade/ConnectivityManagerFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/ConnectivityManagerFacade.java
@@ -16,6 +16,8 @@
package com.googlecode.android_scripting.facade;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+
import android.app.Service;
import android.app.usage.NetworkStats;
import android.app.usage.NetworkStats.Bucket;
@@ -36,14 +38,18 @@
import android.net.ProxyInfo;
import android.net.RouteInfo;
import android.net.Uri;
+import android.net.wifi.WifiNetworkSpecifier;
import android.os.Bundle;
import android.os.RemoteException;
import android.provider.Settings;
+import com.android.modules.utils.build.SdkLevel;
+
import com.google.common.io.ByteStreams;
import com.googlecode.android_scripting.FileUtils;
import com.googlecode.android_scripting.Log;
import com.googlecode.android_scripting.facade.wifi.WifiAwareManagerFacade;
+import com.googlecode.android_scripting.facade.wifi.WifiManagerFacade;
import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
import com.googlecode.android_scripting.rpc.Rpc;
import com.googlecode.android_scripting.rpc.RpcOptional;
@@ -66,6 +72,7 @@
import java.net.SocketException;
import java.net.URL;
import java.net.URLConnection;
+import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
@@ -122,7 +129,19 @@
}
}
- class NetworkCallback extends ConnectivityManager.NetworkCallback {
+ /**
+ * Used to dispatch to a different constructor depending on R or S, since
+ * {@link ConnectivityManager.NetworkCallback#NetworkCallback(int)} was added in S.
+ */
+ private NetworkCallback newNetworkCallback(int events) {
+ if (SdkLevel.isAtLeastS()) {
+ return new NetworkCallback(events);
+ } else {
+ return new NetworkCallback(events, false);
+ }
+ }
+
+ private class NetworkCallback extends ConnectivityManager.NetworkCallback {
public static final int EVENT_INVALID = -1;
public static final int EVENT_NONE = 0;
public static final int EVENT_PRECHECK = 1 << 0;
@@ -135,23 +154,39 @@
public static final int EVENT_RESUMED = 1 << 7;
public static final int EVENT_LINK_PROPERTIES_CHANGED = 1 << 8;
public static final int EVENT_BLOCKED_STATUS_CHANGED = 1 << 9;
- public static final int EVENT_ALL = EVENT_PRECHECK |
- EVENT_AVAILABLE |
- EVENT_LOSING |
- EVENT_LOST |
- EVENT_UNAVAILABLE |
- EVENT_CAPABILITIES_CHANGED |
- EVENT_SUSPENDED |
- EVENT_RESUMED |
- EVENT_LINK_PROPERTIES_CHANGED
- | EVENT_BLOCKED_STATUS_CHANGED;
+ public static final int EVENT_ALL =
+ EVENT_PRECHECK
+ | EVENT_AVAILABLE
+ | EVENT_LOSING
+ | EVENT_LOST
+ | EVENT_UNAVAILABLE
+ | EVENT_CAPABILITIES_CHANGED
+ | EVENT_SUSPENDED
+ | EVENT_RESUMED
+ | EVENT_LINK_PROPERTIES_CHANGED
+ | EVENT_BLOCKED_STATUS_CHANGED;
private int mEvents;
public String mId;
private long mCreateTimestamp;
- public NetworkCallback(int events) {
+ /** Called in >= Android S where super(int) does exist. */
+ private NetworkCallback(int events) {
+ super(ConnectivityManager.NetworkCallback.FLAG_INCLUDE_LOCATION_INFO);
+ init(events);
+ }
+
+ /**
+ * Called in <= Android R where super(int) doesn't exist.
+ * @param ignore placeholder argument to differentiate between R and S constructors' method
+ * signatures.
+ */
+ private NetworkCallback(int events, boolean ignore) {
super();
+ init(events);
+ }
+
+ private void init(int events) {
mEvents = events;
mId = this.toString();
mCreateTimestamp = System.currentTimeMillis();
@@ -431,7 +466,7 @@
builder.setSignalStrength((int) rssi);
builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
NetworkRequest networkRequest = builder.build();
- mNetworkCallback = new NetworkCallback(NetworkCallback.EVENT_ALL);
+ mNetworkCallback = newNetworkCallback(NetworkCallback.EVENT_ALL);
mManager.registerNetworkCallback(networkRequest, mNetworkCallback);
String key = mNetworkCallback.mId;
mNetworkCallbackMap.put(key, mNetworkCallback);
@@ -473,16 +508,19 @@
Log.d("build ClearCapabilities");
builder.clearCapabilities();
}
- if (configJson.has("TransportType")) {
- Log.d("build TransportType" + configJson.getInt("TransportType"));
- builder.addTransportType(configJson.getInt("TransportType"));
+ if (configJson.has(ConnectivityConstants.NET_CAPABILITIES_TRANSPORT_TYPE)) {
+ Log.d("build TransportType"
+ + configJson.getInt(ConnectivityConstants.NET_CAPABILITIES_TRANSPORT_TYPE));
+ builder.addTransportType(
+ configJson.getInt(ConnectivityConstants.NET_CAPABILITIES_TRANSPORT_TYPE));
}
if (configJson.has("SignalStrength")) {
Log.d("build SignalStrength" + configJson.getInt("SignalStrength"));
builder.setSignalStrength(configJson.getInt("SignalStrength"));
}
- if (configJson.has("Capability")) {
- JSONArray capabilities = configJson.getJSONArray("Capability");
+ if (configJson.has(ConnectivityConstants.NET_CAPABILITIES_CAPABILITIES)) {
+ JSONArray capabilities =
+ configJson.getJSONArray(ConnectivityConstants.NET_CAPABILITIES_CAPABILITIES);
for (int i = 0; i < capabilities.length(); i++) {
Log.d("build Capability" + capabilities.getInt(i));
builder.addCapability(capabilities.getInt(i));
@@ -507,7 +545,7 @@
public String connectivityRegisterNetworkCallback(@RpcParameter(name = "configJson")
JSONObject configJson) throws JSONException {
NetworkRequest networkRequest = buildNetworkRequestFromJson(configJson);
- mNetworkCallback = new NetworkCallback(NetworkCallback.EVENT_ALL);
+ mNetworkCallback = newNetworkCallback(NetworkCallback.EVENT_ALL);
mManager.registerNetworkCallback(networkRequest, mNetworkCallback);
String key = mNetworkCallback.mId;
mNetworkCallbackMap.put(key, mNetworkCallback);
@@ -529,7 +567,7 @@
@Rpc(description = "register a default network callback")
public String connectivityRegisterDefaultNetworkCallback() {
- mNetworkCallback = new NetworkCallback(NetworkCallback.EVENT_ALL);
+ mNetworkCallback = newNetworkCallback(NetworkCallback.EVENT_ALL);
mManager.registerDefaultNetworkCallback(mNetworkCallback);
String key = mNetworkCallback.mId;
mNetworkCallbackMap.put(key, mNetworkCallback);
@@ -540,7 +578,7 @@
public String connectivityRequestNetwork(@RpcParameter(name = "configJson")
JSONObject configJson) throws JSONException {
NetworkRequest networkRequest = buildNetworkRequestFromJson(configJson);
- mNetworkCallback = new NetworkCallback(NetworkCallback.EVENT_ALL);
+ mNetworkCallback = newNetworkCallback(NetworkCallback.EVENT_ALL);
mManager.requestNetwork(networkRequest, mNetworkCallback);
String key = mNetworkCallback.mId;
mNetworkCallbackMap.put(key, mNetworkCallback);
@@ -551,13 +589,41 @@
public String connectivityRequestWifiAwareNetwork(@RpcParameter(name = "configJson")
JSONObject configJson) throws JSONException {
NetworkRequest networkRequest = buildWifiAwareNetworkRequestFromJson(configJson);
- mNetworkCallback = new NetworkCallback(NetworkCallback.EVENT_ALL);
+ mNetworkCallback = newNetworkCallback(NetworkCallback.EVENT_ALL);
mManager.requestNetwork(networkRequest, mNetworkCallback);
String key = mNetworkCallback.mId;
mNetworkCallbackMap.put(key, mNetworkCallback);
return key;
}
+ /**
+ * Initiates a network request {@link NetworkRequest} using {@link WifiNetworkSpecifier}.
+ *
+ * @param wNs JSONObject Dictionary of wifi network specifier parameters
+ * @param timeoutInMs Timeout for the request. 0 indicates no timeout.
+ * @throws JSONException
+ * @throws GeneralSecurityException
+ */
+ @Rpc(description = "Initiates a network request using the provided network specifier")
+ public String connectivityRequestWifiNetwork(
+ @RpcParameter(name = "wifiNetworkSpecifier") JSONObject wNs,
+ @RpcParameter(name = "timeoutInMS") Integer timeoutInMs)
+ throws JSONException, GeneralSecurityException {
+ NetworkRequest networkRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI)
+ .setNetworkSpecifier(WifiManagerFacade.genWifiNetworkSpecifier(wNs))
+ .build();
+ mNetworkCallback = newNetworkCallback(NetworkCallback.EVENT_ALL);
+ if (timeoutInMs != 0) {
+ mManager.requestNetwork(networkRequest, mNetworkCallback, timeoutInMs);
+ } else {
+ mManager.requestNetwork(networkRequest, mNetworkCallback);
+ }
+ String key = mNetworkCallback.mId;
+ mNetworkCallbackMap.put(key, mNetworkCallback);
+ return key;
+ }
+
@Rpc(description = "Stop listening for connectivity changes")
public void connectivityStopTrackingConnectivityStateChange() {
if (mTrackingConnectivityStateChange) {
@@ -601,6 +667,16 @@
return mManager.getAllNetworkInfo();
}
+ @Rpc(description = "Get connection status information about all network types supported by the device.")
+ public NetworkCapabilities[] connectivityNetworkGetAllCapabilities() {
+ Network[] networks = mManager.getAllNetworks();
+ NetworkCapabilities[] networkCapabilties = new NetworkCapabilities[networks.length];
+ for (int i = 0; i < networks.length; i++) {
+ networkCapabilties[i] = mManager.getNetworkCapabilities(networks[i]);
+ }
+ return networkCapabilties;
+ }
+
@Rpc(description = "Check whether the active network is connected to the Internet.")
public Boolean connectivityNetworkIsConnected() {
NetworkInfo current = mManager.getActiveNetworkInfo();
@@ -1042,5 +1118,8 @@
@Override
public void shutdown() {
connectivityStopTrackingConnectivityStateChange();
+ for (NetworkCallback networkCallback : mNetworkCallbackMap.values()) {
+ mManager.unregisterNetworkCallback(networkCallback);
+ }
}
}
diff --git a/Common/src/com/googlecode/android_scripting/facade/media/MediaSessionFacade.java b/Common/src/com/googlecode/android_scripting/facade/media/MediaSessionFacade.java
index ad16dc9..5b4e199 100644
--- a/Common/src/com/googlecode/android_scripting/facade/media/MediaSessionFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/media/MediaSessionFacade.java
@@ -16,19 +16,15 @@
package com.googlecode.android_scripting.facade.media;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
-
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.media.session.MediaController;
import android.media.session.MediaSession;
+import android.media.session.MediaSession.Callback;
import android.media.session.MediaSessionManager;
import android.media.session.MediaSessionManager.OnActiveSessionsChangedListener;
import android.media.session.PlaybackState;
-import android.media.session.MediaSession.Callback;
import android.view.KeyEvent;
import com.googlecode.android_scripting.Log;
@@ -40,6 +36,10 @@
import com.googlecode.android_scripting.rpc.RpcDefault;
import com.googlecode.android_scripting.rpc.RpcParameter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
/**
* Expose functionalities of MediaSession related classes
* like MediaSession, MediaSessionManager, MediaController.
@@ -146,8 +146,8 @@
}
KeyEvent keyDown = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
KeyEvent keyUp = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
- mManager.dispatchMediaKeyEvent(keyDown);
- mManager.dispatchMediaKeyEvent(keyUp);
+ mManager.dispatchMediaKeyEvent(keyDown, false);
+ mManager.dispatchMediaKeyEvent(keyUp, false);
}
private MediaController getMediaController(int idx) {
diff --git a/Common/src/com/googlecode/android_scripting/facade/telephony/SmsFacade.java b/Common/src/com/googlecode/android_scripting/facade/telephony/SmsFacade.java
index fa9170a..1de1716 100644
--- a/Common/src/com/googlecode/android_scripting/facade/telephony/SmsFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/telephony/SmsFacade.java
@@ -741,7 +741,7 @@
private PendingIntent createBroadcastPendingIntent(String intentAction, Uri messageUri) {
Intent intent = new Intent(intentAction, messageUri);
- return PendingIntent.getBroadcast(mService, 0, intent, 0);
+ return PendingIntent.getBroadcast(mService, 0, intent, PendingIntent.FLAG_MUTABLE);
}
private static String getSmsFailureReason(int resultCode) {
diff --git a/Common/src/com/googlecode/android_scripting/facade/telephony/TelephonyManagerFacade.java b/Common/src/com/googlecode/android_scripting/facade/telephony/TelephonyManagerFacade.java
index f09d0e2..e60e5f1 100644
--- a/Common/src/com/googlecode/android_scripting/facade/telephony/TelephonyManagerFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/telephony/TelephonyManagerFacade.java
@@ -805,7 +805,7 @@
boolean wasAlwaysAllow = mTelephonyManager.isMobileDataPolicyEnabled(
TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED);
mTelephonyManager.createForSubscriptionId(subId)
- .setMobileDataPolicyEnabledStatus(
+ .setMobileDataPolicyEnabled(
TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED, alwaysAllow);
return wasAlwaysAllow == alwaysAllow;
}
diff --git a/Common/src/com/googlecode/android_scripting/facade/wifi/WifiAwareManagerFacade.java b/Common/src/com/googlecode/android_scripting/facade/wifi/WifiAwareManagerFacade.java
index af07b3c..c690a38 100644
--- a/Common/src/com/googlecode/android_scripting/facade/wifi/WifiAwareManagerFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/wifi/WifiAwareManagerFacade.java
@@ -882,6 +882,16 @@
mResults.putString("messageAsString", new String(message));
postEvent("WifiAwareSessionOnMessageReceived", mResults);
}
+
+ @Override
+ public void onServiceLost(PeerHandle peerHandle, @WifiAwareManager.DiscoveryLostReasonCode
+ int reason) {
+ Bundle mResults = new Bundle();
+ mResults.putInt("discoverySessionId", mDiscoverySessionId);
+ mResults.putInt("peerId", peerHandle.peerId);
+ mResults.putInt("lostReason", reason);
+ postEvent("WifiAwareSessionOnServiceLost", mResults);
+ }
}
class WifiAwareRangingListener implements RttManager.RttListener {
diff --git a/Common/src/com/googlecode/android_scripting/facade/wifi/WifiManagerFacade.java b/Common/src/com/googlecode/android_scripting/facade/wifi/WifiManagerFacade.java
index c02a886..0b1318f 100755
--- a/Common/src/com/googlecode/android_scripting/facade/wifi/WifiManagerFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/wifi/WifiManagerFacade.java
@@ -16,10 +16,15 @@
package com.googlecode.android_scripting.facade.wifi;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.wifi.WifiScanner.WIFI_BAND_24_GHZ;
+import static android.net.wifi.WifiScanner.WIFI_BAND_5_GHZ;
import static com.googlecode.android_scripting.jsonrpc.JsonBuilder.build;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -30,11 +35,13 @@
import android.net.DhcpInfo;
import android.net.MacAddress;
import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.net.Uri;
+import android.net.wifi.CoexUnsafeChannel;
import android.net.wifi.EasyConnectStatusCallback;
import android.net.wifi.ScanResult;
import android.net.wifi.SoftApCapability;
@@ -49,6 +56,7 @@
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.NetworkRequestMatchCallback;
import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
+import android.net.wifi.WifiManager.SubsystemRestartTrackingCallback;
import android.net.wifi.WifiManager.WifiLock;
import android.net.wifi.WifiNetworkSpecifier;
import android.net.wifi.WifiNetworkSuggestion;
@@ -67,8 +75,11 @@
import android.text.TextUtils;
import android.util.Base64;
import android.util.SparseArray;
+import android.util.SparseIntArray;
+
import com.android.internal.annotations.GuardedBy;
+import com.android.modules.utils.build.SdkLevel;
import com.googlecode.android_scripting.Log;
import com.googlecode.android_scripting.facade.EventFacade;
@@ -101,8 +112,8 @@
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
@@ -133,15 +144,17 @@
private final WifiScanResultsReceiver mWifiScanResultsReceiver;
private final WifiStateChangeReceiver mStateChangeReceiver;
private final WifiNetworkSuggestionStateChangeReceiver mNetworkSuggestionStateChangeReceiver;
+ private SubsystemRestartTrackingCallbackFacade mSubsystemRestartTrackingCallback = null;
private final HandlerThread mCallbackHandlerThread;
private final Object mCallbackLock = new Object();
- private final Map<NetworkSpecifier, NetworkCallback> mNetworkCallbacks = new HashMap<>();
private boolean mTrackingWifiStateChange;
private boolean mTrackingTetherStateChange;
private boolean mTrackingNetworkSuggestionStateChange;
@GuardedBy("mCallbackLock")
private NetworkRequestUserSelectionCallback mNetworkRequestUserSelectionCallback;
private final SparseArray<SoftApCallbackImp> mSoftapCallbacks;
+ // This is null if SdkLevel is not at least S
+ @Nullable private WifiManager.CoexCallback mCoexCallback;
private final BroadcastReceiver mTetherStateReceiver = new BroadcastReceiver() {
@Override
@@ -208,25 +221,6 @@
}
};
- private final class NetworkCallbackImpl extends NetworkCallback {
- private static final String EVENT_TAG = mEventType + "NetworkCallback";
-
- @Override
- public void onAvailable(Network network) {
- mEventFacade.postEvent(EVENT_TAG + "OnAvailable", mWifi.getConnectionInfo());
- }
-
- @Override
- public void onUnavailable() {
- mEventFacade.postEvent(EVENT_TAG + "OnUnavailable", null);
- }
-
- @Override
- public void onLost(Network network) {
- mEventFacade.postEvent(EVENT_TAG + "OnLost", null);
- }
- };
-
private static class SoftApCallbackImp implements WifiManager.SoftApCallback {
// A monotonic increasing counter for softap callback ids.
private static int sCount = 0;
@@ -252,21 +246,36 @@
@Override
public void onConnectedClientsChanged(List<WifiClient> clients) {
- ArrayList<String> macAddresses = new ArrayList<>();
- clients.forEach(x -> macAddresses.add(x.getMacAddress().toString()));
+ ArrayList<MacAddress> macAddresses = new ArrayList<>();
+ clients.forEach(x -> macAddresses.add(x.getMacAddress()));
Bundle msg = new Bundle();
msg.putInt("NumClients", clients.size());
- msg.putStringArrayList("MacAddresses", macAddresses);
+ msg.putParcelableArrayList("MacAddresses", macAddresses);
mEventFacade.postEvent(mEventStr + "OnNumClientsChanged", msg);
mEventFacade.postEvent(mEventStr + "OnConnectedClientsChanged", clients);
}
@Override
+ public void onConnectedClientsChanged(SoftApInfo info, List<WifiClient> clients) {
+ ArrayList<MacAddress> macAddresses = new ArrayList<>();
+ clients.forEach(x -> macAddresses.add(x.getMacAddress()));
+ Bundle msg = new Bundle();
+ msg.putParcelable("Info", info);
+ msg.putParcelableArrayList("ClientsMacAddress", macAddresses);
+ mEventFacade.postEvent(mEventStr + "OnConnectedClientsChangedWithInfo", msg);
+ }
+
+ @Override
public void onInfoChanged(SoftApInfo softApInfo) {
mEventFacade.postEvent(mEventStr + "OnInfoChanged", softApInfo);
}
@Override
+ public void onInfoChanged(List<SoftApInfo> infos) {
+ mEventFacade.postEvent(mEventStr + "OnInfoListChanged", infos);
+ }
+
+ @Override
public void onCapabilityChanged(SoftApCapability softApCapability) {
mEventFacade.postEvent(mEventStr + "OnCapabilityChanged", softApCapability);
}
@@ -280,6 +289,31 @@
}
};
+ private static class CoexCallbackImpl extends WifiManager.CoexCallback {
+ private final EventFacade mEventFacade;
+ private final String mEventStr;
+
+ CoexCallbackImpl(EventFacade eventFacade) {
+ mEventFacade = eventFacade;
+ mEventStr = mEventType + "CoexCallback";
+ }
+
+ @Override
+ public void onCoexUnsafeChannelsChanged(
+ @NonNull List<CoexUnsafeChannel> unsafeChannels, int restrictions) {
+ Bundle event = new Bundle();
+ try {
+ event.putString("KEY_COEX_UNSAFE_CHANNELS",
+ coexUnsafeChannelsToJson(unsafeChannels).toString());
+ event.putString("KEY_COEX_RESTRICTIONS",
+ coexRestrictionsToJson(restrictions).toString());
+ mEventFacade.postEvent(mEventStr + "#onCoexUnsafeChannelsChanged", event);
+ } catch (JSONException e) {
+ Log.e("Failed to post event for onCoexUnsafeChannelsChanged: " + e);
+ }
+ }
+ };
+
private WifiLock mLock = null;
private boolean mIsConnected = false;
@@ -313,6 +347,9 @@
mTrackingNetworkSuggestionStateChange = false;
mCallbackHandlerThread.start();
mSoftapCallbacks = new SparseArray<>();
+ if (SdkLevel.isAtLeastS()) {
+ mCoexCallback = new CoexCallbackImpl(mEventFacade);
+ }
}
private void makeLock(int wifiMode) {
@@ -395,6 +432,53 @@
public class WifiStateChangeReceiver extends BroadcastReceiver {
String mCachedWifiInfo = "";
+ /**
+ * When a peer to peer request is active, WifiManager.getConnectionInfo() returns
+ * the peer to peer connection details. Hence use networking API's to retrieve the
+ * internet connection details.
+ *
+ * But on Android R, we will need to fallback to the legacy getConnectionInfo() API since
+ * WifiInfo doesn't implement TransportInfo.
+ */
+ private WifiInfo getInternetConnectivityWifiInfo() {
+ if (!SdkLevel.isAtLeastS()) {
+ return mWifi.getConnectionInfo();
+ }
+ // TODO (b/156867433): We need a location sensitive synchronous API proposed
+ // in aosp/1629501.
+ final CountDownLatch waitForNetwork = new CountDownLatch(1);
+ final class AnswerBox {
+ public WifiInfo wifiInfo;
+ }
+ final AnswerBox answerBox = new AnswerBox();
+ final NetworkCallback networkCallback =
+ new NetworkCallback(NetworkCallback.FLAG_INCLUDE_LOCATION_INFO) {
+ @Override
+ public void onCapabilitiesChanged(@NonNull Network network,
+ @NonNull NetworkCapabilities networkCapabilities) {
+ answerBox.wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo();
+ waitForNetwork.countDown();
+ }
+ };
+ mCm.registerNetworkCallback(
+ new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI)
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .build(), networkCallback);
+ try {
+ if (!waitForNetwork.await(5, TimeUnit.SECONDS)) {
+ Log.e("Timed out waiting for network to connect");
+ return null;
+ }
+ return answerBox.wifiInfo;
+ } catch (InterruptedException e) {
+ Log.e("Waiting for onAvailable failed", e);
+ return null;
+ } finally {
+ mCm.unregisterNetworkCallback(networkCallback);
+ }
+ }
+
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
@@ -405,7 +489,12 @@
// If network info is of type wifi, send wifi events.
if (nInfo.getType() == ConnectivityManager.TYPE_WIFI) {
if (nInfo.getDetailedState().equals(DetailedState.CONNECTED)) {
- WifiInfo wInfo = mWifi.getConnectionInfo();
+ WifiInfo wInfo = getInternetConnectivityWifiInfo();
+ if (wInfo == null) {
+ Log.e("Failed to get WifiInfo for internet connection. "
+ + "Not sending wifi network connection event");
+ return;
+ }
String bssid = wInfo.getBSSID();
if (bssid != null && !mCachedWifiInfo.equals(wInfo.toString())) {
Log.d("WifiNetworkConnected");
@@ -519,28 +608,26 @@
// Check if new security type SAE (WPA3) is present. Default to PSK
if (j.has("security")) {
if (TextUtils.equals(j.getString("security"), "SAE")) {
- config.allowedKeyManagement.set(KeyMgmt.SAE);
- config.requirePmf = true;
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
} else {
- config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
}
} else {
- config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
}
config.preSharedKey = "\"" + j.getString("password") + "\"";
} else if (j.has("preSharedKey")) {
- config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
config.preSharedKey = j.getString("preSharedKey");
} else {
if (j.has("security")) {
if (TextUtils.equals(j.getString("security"), "OWE")) {
- config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
- config.requirePmf = true;
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE);
} else {
- config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);
}
} else {
- config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);
}
}
if (j.has("BSSID")) {
@@ -557,9 +644,7 @@
}
if (j.has("wepKeys")) {
// Looks like we only support static WEP.
- config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
- config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
- config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_WEP);
JSONArray keys = j.getJSONArray("wepKeys");
String[] wepKeys = new String[keys.length()];
for (int i = 0; i < keys.length(); i++) {
@@ -582,7 +667,7 @@
return config;
}
- private WifiEnterpriseConfig genWifiEnterpriseConfig(JSONObject j) throws JSONException,
+ private static WifiEnterpriseConfig genWifiEnterpriseConfig(JSONObject j) throws JSONException,
GeneralSecurityException {
WifiEnterpriseConfig eConfig = new WifiEnterpriseConfig();
if (j.has(WifiEnterpriseConfig.EAP_KEY)) {
@@ -605,7 +690,11 @@
Log.v("Client Cert String is " + certStr);
Log.v("Client Key String is " + keyStr);
X509Certificate cert = strToX509Cert(certStr);
- PrivateKey privKey = strToPrivateKey(keyStr);
+ String certAlgo = "RSA";
+ if (j.has("cert_algo")) {
+ certAlgo = j.getString("cert_algo");
+ }
+ PrivateKey privKey = strToPrivateKey(keyStr, certAlgo);
Log.v("Cert is " + cert);
Log.v("Private Key is " + privKey);
eConfig.setClientKeyEntry(privKey, cert);
@@ -649,13 +738,11 @@
return null;
}
WifiConfiguration config = new WifiConfiguration();
- config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
- config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
if (j.has("security")) {
if (TextUtils.equals(j.getString("security"), "SUITE_B_192")) {
- config.allowedKeyManagement.set(KeyMgmt.SUITE_B_192);
- config.requirePmf = true;
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);
}
}
@@ -685,7 +772,10 @@
return config;
}
- private NetworkSpecifier genWifiNetworkSpecifier(JSONObject j) throws JSONException,
+ /**
+ * Generate {@link WifiNetworkSpecifier} from the specified json.
+ */
+ public static NetworkSpecifier genWifiNetworkSpecifier(JSONObject j) throws JSONException,
GeneralSecurityException {
if (j == null) {
return null;
@@ -794,6 +884,11 @@
}
}
}
+ if (j.has("enhancedMacRandomizationEnabled")
+ && j.getBoolean("enhancedMacRandomizationEnabled")) {
+ builder = builder.setMacRandomizationSetting(
+ WifiNetworkSuggestion.RANDOMIZATION_NON_PERSISTENT);
+ }
return builder.build();
}
@@ -837,22 +932,22 @@
return info;
}
- private byte[] base64StrToBytes(String input) {
+ private static byte[] base64StrToBytes(String input) {
return Base64.decode(input, Base64.DEFAULT);
}
- private X509Certificate strToX509Cert(String certStr) throws CertificateException {
+ private static X509Certificate strToX509Cert(String certStr) throws CertificateException {
byte[] certBytes = base64StrToBytes(certStr);
InputStream certStream = new ByteArrayInputStream(certBytes);
CertificateFactory cf = CertificateFactory.getInstance("X509");
return (X509Certificate) cf.generateCertificate(certStream);
}
- private PrivateKey strToPrivateKey(String key) throws NoSuchAlgorithmException,
- InvalidKeySpecException {
+ private static PrivateKey strToPrivateKey(String key, String algo)
+ throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] keyBytes = base64StrToBytes(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
- KeyFactory fact = KeyFactory.getInstance("RSA");
+ KeyFactory fact = KeyFactory.getInstance(algo);
PrivateKey priv = fact.generatePrivate(keySpec);
return priv;
}
@@ -1083,6 +1178,27 @@
}
}
+ private class SubsystemRestartTrackingCallbackFacade extends SubsystemRestartTrackingCallback {
+ private final EventFacade mEventFacade;
+
+ SubsystemRestartTrackingCallbackFacade(EventFacade eventFacade) {
+ super();
+ mEventFacade = eventFacade;
+ }
+
+ @Override
+ public void onSubsystemRestarting() {
+ Log.v("onSubsystemRestarting");
+ mEventFacade.postEvent("WifiSubsystemRestarting", null);
+ }
+
+ @Override
+ public void onSubsystemRestarted() {
+ Log.v("onSubsystemRestarted");
+ mEventFacade.postEvent("WifiSubsystemRestarted", null);
+ }
+ }
+
private OsuProvider buildTestOsuProvider(JSONObject config) {
String osuServiceDescription = "Google Passpoint Test Service";
List<Integer> osuMethodList =
@@ -1233,6 +1349,41 @@
return mWifi.getConnectionInfo();
}
+ /**
+ * Check if wifi network is temporary disabled.
+ * @param config JSONObject Dictionary of wifi connection parameters.
+ * @return True if network is disabled temporarily, False if not.
+ */
+ @Rpc(description = "Check if network is temporary disabled")
+ public boolean wifiIsNetworkTemporaryDisabledForNetwork(
+ @RpcParameter(name = "config") JSONObject config)
+ throws JSONException, GeneralSecurityException {
+ WifiConfiguration wifiConfig;
+ if (config.has(WifiEnterpriseConfig.EAP_KEY)) {
+ wifiConfig = genWifiConfigWithEnterpriseConfig(config);
+ } else {
+ wifiConfig = genWifiConfig(config);
+ }
+ List<WifiConfiguration> wifiConfigList = wifiGetConfiguredNetworks();
+ for (WifiConfiguration conf : wifiConfigList) {
+ if (conf.getSsidAndSecurityTypeString().equals(
+ wifiConfig.getSsidAndSecurityTypeString())) {
+ Log.d("Found matching config in the configured networks.");
+ return conf.getNetworkSelectionStatus().isNetworkTemporaryDisabled();
+ }
+ }
+ Log.d("Wifi config is not in list of configured wifi networks.");
+ return false;
+ }
+
+ /**
+ * Get wifi standard for wifi connection.
+ */
+ @Rpc(description = "Return connection WiFi standard")
+ public Integer wifiGetConnectionStandard() {
+ return mWifi.getConnectionInfo().getWifiStandard();
+ }
+
@Rpc(description = "Returns wifi activity and energy usage info.")
public WifiActivityEnergyInfo wifiGetControllerActivityEnergyInfo() {
WifiActivityEnergyInfo[] mutable = {null};
@@ -1296,14 +1447,51 @@
return mWifi.isVerboseLoggingEnabled() ? 1 : 0;
}
+ /**
+ * Query whether or not the device supports concurrency of Station (STA) + multiple access
+ * points (AP) (where the APs bridged together).
+ *
+ * @return true if this device supports concurrency of STA + multiple APs which are bridged
+ * together, false otherwise.
+ */
+ @Rpc(description = "true if this adapter supports STA + bridged Soft AP concurrency.")
+ public Boolean wifiIsStaBridgedApConcurrencySupported() {
+ return mWifi.isStaBridgedApConcurrencySupported();
+ }
+
+ /**
+ * Query whether or not the device supports multiple Access point (AP) which are bridged
+ * together.
+ *
+ * @return true if this device supports concurrency of multiple AP which bridged together,
+ * false otherwise.
+ */
+ @Rpc(description = "true if this adapter supports bridged Soft AP concurrency.")
+ public Boolean wifiIsBridgedApConcurrencySupported() {
+ return mWifi.isBridgedApConcurrencySupported();
+ }
+
@Rpc(description = "true if this adapter supports 5 GHz band.")
public Boolean wifiIs5GHzBandSupported() {
return mWifi.is5GHzBandSupported();
}
- @Rpc(description = "true if this adapter supports multiple simultaneous connections.")
- public Boolean wifiIsAdditionalStaSupported() {
- return mWifi.isAdditionalStaSupported();
+ @Rpc(description = "true if this adapter supports multiple simultaneous connections for"
+ + "local only use-case.")
+ public Boolean wifiIsStaConcurrencyForLocalOnlyConnectionsSupported() {
+ return mWifi.isStaConcurrencyForLocalOnlyConnectionsSupported();
+ }
+
+ @Rpc(description = "true if this adapter supports multiple simultaneous connections for mbb "
+ + "wifi to wifi switching.")
+ public Boolean wifiIsMakeBeforeBreakWifiSwitchingSupported() {
+ return mWifi.isMakeBeforeBreakWifiSwitchingSupported();
+ }
+
+ @Rpc(description = "true if this adapter supports multiple simultaneous connections for "
+ + "restricted connection use-case.")
+ public Boolean wifiIsStaConcurrencyForRestrictedConnectionsSupported() {
+ return mWifi.isStaConcurrencyForRestrictedConnectionsSupported();
}
@Rpc(description = "Check if the chipset supports a certain Wi-Fi standard.", returns = "true if standard is supported")
@@ -1418,6 +1606,17 @@
public Boolean wifiIsEnhancedOpenSupported() {
return mWifi.isEnhancedOpenSupported();
}
+
+ /**
+ * @return true if this device supports Wi-Fi Device Provisioning Protocol (Easy-connect)
+ * Enrollee Responder mode
+ */
+ @Rpc(description = "Check if Easy Connect (DPP) Enrollee responder mode is supported "
+ + "on this device.")
+ public Boolean wifiIsEasyConnectEnrolleeResponderModeSupported() {
+ return mWifi.isEasyConnectEnrolleeResponderModeSupported();
+ }
+
/**
* @return true if this device supports Wi-Fi Device Provisioning Protocol (Easy-connect)
*/
@@ -1469,6 +1668,30 @@
return mWifi.removeNetwork(netId);
}
+ private int getApBandFromChannelFrequency(int freq) {
+ if (ScanResult.is24GHz(freq)) {
+ return SoftApConfiguration.BAND_2GHZ;
+ } else if (ScanResult.is5GHz(freq)) {
+ return SoftApConfiguration.BAND_5GHZ;
+ } else if (ScanResult.is6GHz(freq)) {
+ return SoftApConfiguration.BAND_6GHZ;
+ } else if (ScanResult.is60GHz(freq)) {
+ return SoftApConfiguration.BAND_60GHZ;
+ }
+ return -1;
+ }
+
+ private int[] convertJSONArrayToIntArray(JSONArray jArray) throws JSONException {
+ if (jArray == null) {
+ return null;
+ }
+ int[] iArray = new int[jArray.length()];
+ for (int i = 0; i < jArray.length(); i++) {
+ iArray[i] = jArray.getInt(i);
+ }
+ return iArray;
+ }
+
private SoftApConfiguration createSoftApConfiguration(JSONObject configJson)
throws JSONException {
if (configJson == null) {
@@ -1539,10 +1762,48 @@
for (int j = 0; j < blockedList.length(); j++) {
blockedClientList.add(MacAddress.fromString(blockedList.getString(j)));
}
-
}
+
configBuilder.setAllowedClientList(allowedClientList);
configBuilder.setBlockedClientList(blockedClientList);
+
+ if (SdkLevel.isAtLeastS()) {
+ if (configJson.has("apBands")) {
+ JSONArray jBands = configJson.getJSONArray("apBands");
+ int[] bands = convertJSONArrayToIntArray(jBands);
+ configBuilder.setBands(bands);
+ }
+
+ if (configJson.has("apChannelFrequencies")) {
+ JSONArray jChannelFrequencys = configJson.getJSONArray("apChannelFrequencies");
+ int[] channelFrequencies = convertJSONArrayToIntArray(jChannelFrequencys);
+ SparseIntArray channels = new SparseIntArray();
+ for (int channelFrequency : channelFrequencies) {
+ if (channelFrequency != 0) {
+ channels.put(getApBandFromChannelFrequency(channelFrequency),
+ ScanResult.convertFrequencyMhzToChannelIfSupported(
+ channelFrequency));
+ }
+ }
+ if (channels.size() != 0) {
+ configBuilder.setChannels(channels);
+ }
+ }
+
+ if (configJson.has("MacRandomizationSetting")) {
+ configBuilder.setMacRandomizationSetting(
+ configJson.getInt("MacRandomizationSetting"));
+ }
+
+ if (configJson.has("BridgedModeOpportunisticShutdownEnabled")) {
+ configBuilder.setBridgedModeOpportunisticShutdownEnabled(
+ configJson.getBoolean("BridgedModeOpportunisticShutdownEnabled"));
+ }
+
+ if (configJson.has("Ieee80211axEnabled")) {
+ configBuilder.setIeee80211axEnabled(configJson.getBoolean("Ieee80211axEnabled"));
+ }
+ }
return configBuilder.build();
}
@@ -1699,6 +1960,16 @@
return enabled;
}
+ @Rpc(description = "Restart the WiFi subsystem.")
+ public void restartWifiSubsystem() {
+ if (mSubsystemRestartTrackingCallback == null) {
+ // one-time registration if needed
+ mSubsystemRestartTrackingCallback = new SubsystemRestartTrackingCallbackFacade(
+ mEventFacade);
+ }
+ mWifi.restartWifiSubsystem();
+ }
+
@Rpc(description = "Toggle Wifi scan always available on and off.", returns = "True if Wifi scan is always available.")
public Boolean wifiToggleScanAlwaysAvailable(
@RpcParameter(name = "enabled") @RpcOptional Boolean enabled)
@@ -1714,91 +1985,6 @@
mWifi.allowAutojoinGlobal(enable);
}
- private void wifiRequestNetworkWithSpecifierInternal(NetworkSpecifier wns, int timeoutInMs)
- throws GeneralSecurityException {
- NetworkRequest networkRequest = new NetworkRequest.Builder()
- .addTransportType(TRANSPORT_WIFI)
- .setNetworkSpecifier(wns)
- .build();
- NetworkCallback networkCallback = new NetworkCallbackImpl();
- if (timeoutInMs != 0) {
- mCm.requestNetwork(networkRequest, networkCallback,
- new Handler(mCallbackHandlerThread.getLooper()), timeoutInMs);
- } else {
- mCm.requestNetwork(networkRequest, networkCallback,
- new Handler(mCallbackHandlerThread.getLooper()));
- }
- // Store the callback for release later.
- mNetworkCallbacks.put(wns, networkCallback);
- }
-
- /**
- * Initiates a network request {@link NetworkRequest} using {@link WifiNetworkSpecifier}.
- *
- * @param wifiNetworkSpecifier JSONObject Dictionary of wifi network specifier parameters
- * @throws JSONException
- * @throws GeneralSecurityException
- */
- @Rpc(description = "Initiates a network request using the provided network specifier")
- public void wifiRequestNetworkWithSpecifier(
- @RpcParameter(name = "wifiNetworkSpecifier") JSONObject wifiNetworkSpecifier)
- throws JSONException, GeneralSecurityException {
- wifiRequestNetworkWithSpecifierInternal(genWifiNetworkSpecifier(wifiNetworkSpecifier), 0);
- }
-
- /**
- * Initiates a network request {@link NetworkRequest} using {@link WifiNetworkSpecifier}.
- *
- * @param wifiNetworkSpecifier JSONObject Dictionary of wifi network specifier parameters
- * @param timeoutInMs Timeout for the request.
- * @throws JSONException
- * @throws GeneralSecurityException
- */
- @Rpc(description = "Initiates a network request using the provided network specifier")
- public void wifiRequestNetworkWithSpecifierWithTimeout(
- @RpcParameter(name = "wifiNetworkSpecifier") JSONObject wifiNetworkSpecifier,
- @RpcParameter(name = "timeout") Integer timeoutInMs)
- throws JSONException, GeneralSecurityException {
- wifiRequestNetworkWithSpecifierInternal(
- genWifiNetworkSpecifier(wifiNetworkSpecifier), timeoutInMs);
- }
-
- /**
- * Releases network request using {@link WifiNetworkSpecifier}.
- *
- * @throws JSONException
- * @throws GeneralSecurityException
- */
- @Rpc(description = "Releases network request corresponding to the network specifier")
- public void wifiReleaseNetwork(
- @RpcParameter(name = "wifiNetworkSpecifier") JSONObject wifiNetworkSpecifier)
- throws JSONException, GeneralSecurityException {
- NetworkSpecifier wns = genWifiNetworkSpecifier(wifiNetworkSpecifier);
- NetworkCallback networkCallback = mNetworkCallbacks.remove(wns);
- if (networkCallback == null) {
- throw new IllegalArgumentException("network callback is null");
- }
- mCm.unregisterNetworkCallback(networkCallback);
- }
-
- /**
- * Releases all pending network requests.
- *
- * @throws JSONException
- * @throws GeneralSecurityException
- */
- @Rpc(description = "Releases all pending network requests")
- public void wifiReleaseNetworkAll() {
- Iterator<Map.Entry<NetworkSpecifier, NetworkCallback>> it =
- mNetworkCallbacks.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry<NetworkSpecifier, NetworkCallback> entry = it.next();
- NetworkCallback networkCallback = entry.getValue();
- it.remove();
- mCm.unregisterNetworkCallback(networkCallback);
- }
- }
-
/**
* Register network request match callback to simulate the UI flow.
*
@@ -1889,7 +2075,6 @@
@Override
public void shutdown() {
- wifiReleaseNetworkAll();
wifiLockRelease();
if (mTrackingWifiStateChange == true) {
wifiStopTrackingStateChange();
@@ -1989,6 +2174,36 @@
Log.d("Posting event: onProgress");
mEventFacade.postEvent(EASY_CONNECT_CALLBACK_TAG, msg);
}
+
+ @Override
+ public void onBootstrapUriGenerated(@NonNull Uri dppUri) {
+ Bundle msg = new Bundle();
+ msg.putString("Type", "onBootstrapUriGenerated");
+ Log.d("onBootstrapUriGenerated uri: " + dppUri.toString());
+ msg.putString("generatedUri", dppUri.toString());
+ Log.d("Posting event: onBootstrapUriGenerated");
+ mEventFacade.postEvent(EASY_CONNECT_CALLBACK_TAG, msg);
+ }
+ }
+
+ private static @WifiManager.EasyConnectCryptographyCurve
+ int getEasyConnectCryptographyCurve(String curve) {
+
+ switch (curve) {
+ case "secp384r1":
+ return WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1;
+ case "secp521r1":
+ return WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1;
+ case "brainpoolP256r1":
+ return WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1;
+ case "brainpoolP384r1":
+ return WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1;
+ case "brainpoolP512r1":
+ return WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1;
+ case "prime256v1":
+ default:
+ return WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1;
+ }
}
/**
@@ -2032,6 +2247,24 @@
}
/**
+ * Start Easy Connect (DPP) in Responder-Enrollee role: Receive Wi-Fi configuration from a peer
+ *
+ * @param deviceInfo The device specific info to attach in the generated URI
+ * @param cryptographyCurve Elliptic curve cryptography used to generate DPP
+ * public/private key pair
+ */
+ @Rpc(description = "Easy Connect Responder-Enrollee: Receive Wi-Fi configuration from peer")
+ public void startEasyConnectAsEnrolleeResponder(@RpcParameter(name = "deviceInfo") String
+ deviceInfo, @RpcParameter(name = "cryptographyCurve") String cryptographyCurve) {
+ EasyConnectCallback dppStatusCallback = new EasyConnectCallback();
+
+ // Start Easy Connect
+ mWifi.startEasyConnectAsEnrolleeResponder(deviceInfo,
+ getEasyConnectCryptographyCurve(cryptographyCurve), mService.getMainExecutor(),
+ dppStatusCallback);
+ }
+
+ /**
* Stop Easy Connect (DPP) session
*
*/
@@ -2058,4 +2291,165 @@
@RpcParameter(name = "enableAutojoin") Boolean enableAutojoin) {
mWifi.allowAutojoinPasspoint(fqdn, enableAutojoin);
}
+
+ private static CoexUnsafeChannel genCoexUnsafeChannel(JSONObject j) throws JSONException {
+ if (j == null || !j.has("band") || !j.has("channel")) {
+ return null;
+ }
+
+ final int band;
+ final String jsonBand = j.getString("band");
+ if (TextUtils.equals(jsonBand, "24_GHZ")) {
+ band = WIFI_BAND_24_GHZ;
+ } else if (TextUtils.equals(jsonBand, "5_GHZ")) {
+ band = WIFI_BAND_5_GHZ;
+ } else {
+ return null;
+ }
+ if (j.has("powerCapDbm")) {
+ return new CoexUnsafeChannel(band, j.getInt("channel"), j.getInt("powerCapDbm"));
+ }
+ return new CoexUnsafeChannel(band, j.getInt("channel"));
+ }
+
+ private static List<CoexUnsafeChannel> genCoexUnsafeChannels(
+ JSONArray jsonCoexUnsafeChannelsArray) throws JSONException {
+ if (jsonCoexUnsafeChannelsArray == null) {
+ return Collections.emptyList();
+ }
+ List<CoexUnsafeChannel> unsafeChannels = new ArrayList<>();
+ for (int i = 0; i < jsonCoexUnsafeChannelsArray.length(); i++) {
+ unsafeChannels.add(
+ genCoexUnsafeChannel(jsonCoexUnsafeChannelsArray.getJSONObject(i)));
+ }
+ return unsafeChannels;
+ }
+
+ private static int genCoexRestrictions(JSONArray jsonCoexRestrictionArray)
+ throws JSONException {
+ if (jsonCoexRestrictionArray == null) {
+ return 0;
+ }
+ int coexRestrictions = 0;
+ for (int i = 0; i < jsonCoexRestrictionArray.length(); i++) {
+ final String jsonRestriction = jsonCoexRestrictionArray.getString(i);
+ if (TextUtils.equals(jsonRestriction, "WIFI_DIRECT")) {
+ coexRestrictions |= WifiManager.COEX_RESTRICTION_WIFI_DIRECT;
+ }
+ if (TextUtils.equals(jsonRestriction, "SOFTAP")) {
+ coexRestrictions |= WifiManager.COEX_RESTRICTION_SOFTAP;
+ }
+ if (TextUtils.equals(jsonRestriction, "WIFI_AWARE")) {
+ coexRestrictions |= WifiManager.COEX_RESTRICTION_WIFI_AWARE;
+ }
+ }
+ return coexRestrictions;
+ }
+
+ /**
+ * Converts a set of {@link CoexUnsafeChannel} to a {@link JSONArray} of {@link JSONObject} of
+ * format:
+ * {
+ * "band": <"24_GHZ" or "5_GHZ">
+ * "channel" : <Channel Number>
+ * (Optional) "powerCapDbm" : <Power Cap in Dbm>
+ * }
+ */
+ private static JSONArray coexUnsafeChannelsToJson(List<CoexUnsafeChannel> unsafeChannels)
+ throws JSONException {
+ final JSONArray jsonCoexUnsafeChannelArray = new JSONArray();
+ for (CoexUnsafeChannel unsafeChannel : unsafeChannels) {
+ final String jsonBand;
+ if (unsafeChannel.getBand() == WIFI_BAND_24_GHZ) {
+ jsonBand = "24_GHZ";
+ } else if (unsafeChannel.getBand() == WIFI_BAND_5_GHZ) {
+ jsonBand = "5_GHZ";
+ } else {
+ continue;
+ }
+ final JSONObject jsonUnsafeChannel = new JSONObject();
+ jsonUnsafeChannel.put("band", jsonBand);
+ jsonUnsafeChannel.put("channel", unsafeChannel.getChannel());
+ final int powerCapDbm = unsafeChannel.getPowerCapDbm();
+ if (powerCapDbm != CoexUnsafeChannel.POWER_CAP_NONE) {
+ jsonUnsafeChannel.put("powerCapDbm", powerCapDbm);
+ }
+ jsonCoexUnsafeChannelArray.put(jsonUnsafeChannel);
+ }
+ return jsonCoexUnsafeChannelArray;
+ }
+
+ /**
+ * Converts a coex restriction bitmask {@link WifiManager#getCoexRestrictions()} to a JSON array
+ * of possible values "WIFI_DIRECT", "SOFTAP", "WIFI_AWARE".
+ */
+ private static JSONArray coexRestrictionsToJson(int coexRestrictions) {
+ final JSONArray jsonCoexRestrictionArray = new JSONArray();
+ if ((coexRestrictions & WifiManager.COEX_RESTRICTION_WIFI_DIRECT) != 0) {
+ jsonCoexRestrictionArray.put("WIFI_DIRECT");
+ }
+ if ((coexRestrictions & WifiManager.COEX_RESTRICTION_SOFTAP) != 0) {
+ jsonCoexRestrictionArray.put("SOFTAP");
+ }
+ if ((coexRestrictions & WifiManager.COEX_RESTRICTION_WIFI_AWARE) != 0) {
+ jsonCoexRestrictionArray.put("WIFI_AWARE");
+ }
+ return jsonCoexRestrictionArray;
+ }
+
+ /**
+ * Returns whether the default coex algorithm is enabled or not
+ *
+ * @return {@code true} if the default coex algorithm is enabled, {@code false} otherwise.
+ */
+ @Rpc(description = "Returns whether the default coex algorithm is enabled or not")
+ public boolean wifiIsDefaultCoexAlgorithmEnabled() {
+ if (!SdkLevel.isAtLeastS()) {
+ return false;
+ }
+ return mWifi.isDefaultCoexAlgorithmEnabled();
+ }
+
+ /**
+ * Sets the active list of unsafe channels to avoid for coex and the restricted Wifi interfaces.
+ *
+ * @param unsafeChannels JSONArray representation of {@link CoexUnsafeChannel}.
+ * See {@link #coexUnsafeChannelsToJson(List)}.
+ * @param restrictions JSONArray representation of coex restrictions.
+ * See {@link #coexRestrictionsToJson(int)}.
+ * @throws JSONException
+ */
+ @Rpc(description = "Set the unsafe channels to avoid for coex")
+ public void wifiSetCoexUnsafeChannels(
+ @RpcParameter(name = "unsafeChannels") JSONArray unsafeChannels,
+ @RpcParameter(name = "restrictions") JSONArray restrictions) throws JSONException {
+ if (!SdkLevel.isAtLeastS()) {
+ return;
+ }
+ mWifi.setCoexUnsafeChannels(
+ genCoexUnsafeChannels(unsafeChannels), genCoexRestrictions(restrictions));
+ }
+
+ /**
+ * Registers a coex callback to start receiving coex update events.
+ */
+ @Rpc(description = "Registers a coex callback to start receiving coex update events")
+ public void wifiRegisterCoexCallback() {
+ if (!SdkLevel.isAtLeastS()) {
+ return;
+ }
+ mWifi.registerCoexCallback(
+ new HandlerExecutor(mCallbackHandlerThread.getThreadHandler()), mCoexCallback);
+ }
+
+ /**
+ * Unregisters the coex callback to stop receiving coex update events.
+ */
+ @Rpc(description = "Unregisters the coex callback to stop receiving coex update events")
+ public void wifiUnregisterCoexCallback() {
+ if (!SdkLevel.isAtLeastS()) {
+ return;
+ }
+ mWifi.unregisterCoexCallback(mCoexCallback);
+ }
}
diff --git a/Common/src/com/googlecode/android_scripting/facade/wifi/WifiRtt2ManagerFacade.java b/Common/src/com/googlecode/android_scripting/facade/wifi/WifiRtt2ManagerFacade.java
index 5197896..7c1cc00 100644
--- a/Common/src/com/googlecode/android_scripting/facade/wifi/WifiRtt2ManagerFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/wifi/WifiRtt2ManagerFacade.java
@@ -79,7 +79,7 @@
@Override
public void shutdown() {
- // empty
+ mService.unregisterReceiver(mStateChangedReceiver);
}
@Rpc(description = "Does the device support the Wi-Fi RTT feature?")
diff --git a/Common/src/com/googlecode/android_scripting/jsonrpc/JsonBuilder.java b/Common/src/com/googlecode/android_scripting/jsonrpc/JsonBuilder.java
index 99f45d8..739028c 100644
--- a/Common/src/com/googlecode/android_scripting/jsonrpc/JsonBuilder.java
+++ b/Common/src/com/googlecode/android_scripting/jsonrpc/JsonBuilder.java
@@ -36,6 +36,7 @@
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.ProxyInfo;
import android.net.RouteInfo;
@@ -49,8 +50,10 @@
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiScanner;
import android.net.wifi.WifiScanner.ScanData;
import android.net.wifi.WpsInfo;
+import android.net.wifi.aware.WifiAwareNetworkInfo;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pGroup;
@@ -93,12 +96,15 @@
import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import com.android.internal.net.LegacyVpnInfo;
+import com.android.modules.utils.build.SdkLevel;
import com.googlecode.android_scripting.ConvertUtils;
import com.googlecode.android_scripting.Log;
import com.googlecode.android_scripting.event.Event;
+import com.googlecode.android_scripting.facade.ConnectivityConstants;
import com.googlecode.android_scripting.facade.DataUsageController.DataUsageInfo;
import com.googlecode.android_scripting.facade.telephony.InCallServiceImpl;
import com.googlecode.android_scripting.facade.telephony.TelephonyConstants;
@@ -239,6 +245,9 @@
if (data instanceof Network) {
return buildNetwork((Network) data);
}
+ if (data instanceof NetworkCapabilities) {
+ return buildNetworkCapabilities((NetworkCapabilities) data);
+ }
if (data instanceof NetworkInfo) {
return buildNetworkInfo((NetworkInfo) data);
}
@@ -929,6 +938,48 @@
return nw;
}
+ public static JSONObject buildNetworkCapabilities(JSONObject nc, NetworkCapabilities data)
+ throws JSONException {
+ nc.put(ConnectivityConstants.NetworkCallbackContainer.RSSI,
+ data.getSignalStrength());
+ nc.put(ConnectivityConstants.NetworkCallbackContainer.METERED,
+ !data.hasCapability(ConnectivityConstants.NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+ nc.put(ConnectivityConstants.NET_CAPABILITIES_TRANSPORT_TYPE,
+ new JSONArray(data.getTransportTypes()));
+ nc.put(ConnectivityConstants.NET_CAPABILITIES_CAPABILITIES,
+ new JSONArray(data.getCapabilities()));
+
+ if (data.getNetworkSpecifier() != null) {
+ nc.put("network_specifier",
+ data.getNetworkSpecifier().toString());
+ }
+ if (data.getTransportInfo() != null) {
+ nc.put("transport_info",
+ JsonBuilder.build(data.getTransportInfo()));
+ if (data.getTransportInfo() instanceof WifiAwareNetworkInfo) {
+ WifiAwareNetworkInfo anc =
+ (WifiAwareNetworkInfo) data.getTransportInfo();
+
+ String ipv6 = anc.getPeerIpv6Addr().toString();
+ if (ipv6.charAt(0) == '/') {
+ ipv6 = ipv6.substring(1);
+ }
+ nc.put("aware_ipv6", ipv6);
+ if (anc.getPort() != 0) {
+ nc.put("aware_port", anc.getPort());
+ }
+ if (anc.getTransportProtocol() != -1) {
+ nc.put("aware_transport_protocol", anc.getTransportProtocol());
+ }
+ }
+ }
+ return nc;
+ }
+
+ private static Object buildNetworkCapabilities(NetworkCapabilities data) throws JSONException {
+ return buildNetworkCapabilities(new JSONObject(), data);
+ }
+
private static Object buildNetworkInfo(NetworkInfo data)
throws JSONException {
JSONObject info = new JSONObject();
@@ -1057,6 +1108,22 @@
return result;
}
+ private static @WifiScanner.WifiBand int apBand2wifiScannerBand(
+ @SoftApConfiguration.BandType int band) {
+ switch(band) {
+ case SoftApConfiguration.BAND_2GHZ:
+ return WifiScanner.WIFI_BAND_24_GHZ;
+ case SoftApConfiguration.BAND_5GHZ:
+ return WifiScanner.WIFI_BAND_5_GHZ;
+ case SoftApConfiguration.BAND_6GHZ:
+ return WifiScanner.WIFI_BAND_6_GHZ;
+ case SoftApConfiguration.BAND_60GHZ:
+ return WifiScanner.WIFI_BAND_60_GHZ;
+ default:
+ return WifiScanner.WIFI_BAND_UNSPECIFIED;
+ }
+ }
+
private static Object buildSoftApConfiguration(SoftApConfiguration data)
throws JSONException {
JSONObject config = new JSONObject();
@@ -1084,6 +1151,26 @@
config.put("ClientControlByUserEnabled", data.isClientControlByUserEnabled());
config.put("AllowedClientList", build(data.getAllowedClientList()));
config.put("BlockedClientList", build(data.getBlockedClientList()));
+ if (SdkLevel.isAtLeastS()) {
+ config.put("apBands", buildJSONArray(
+ IntStream.of(data.getBands()).boxed().toArray(Integer[]::new)));
+ SparseIntArray channels = data.getChannels();
+ int[] channelFrequencies = new int[channels.size()];
+ for (int i = 0; i < channels.size(); i++) {
+ int channel = channels.valueAt(i);
+ channelFrequencies[i] = channel == 0 ? 0
+ : ScanResult.convertChannelToFrequencyMhzIfSupported(
+ channel, apBand2wifiScannerBand(channels.keyAt(i)));
+ }
+ if (channelFrequencies.length != 0) {
+ config.put("apChannelFrequencies", build(
+ IntStream.of(channelFrequencies).boxed().toArray(Integer[]::new)));
+ }
+ config.put("MacRandomizationSetting", build(data.getMacRandomizationSetting()));
+ config.put("BridgedModeOpportunisticShutdownEnabled",
+ build(data.isBridgedModeOpportunisticShutdownEnabled()));
+ config.put("Ieee80211axEnabled", build(data.isIeee80211axEnabled()));
+ }
return config;
}
@@ -1222,6 +1309,29 @@
SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT));
info.put("wpa3SaeSupported", data.areFeaturesSupported(
SoftApCapability.SOFTAP_FEATURE_WPA3_SAE));
+ info.put("ieee80211axSupported", data.areFeaturesSupported(
+ SoftApCapability.SOFTAP_FEATURE_IEEE80211_AX));
+ info.put("24gSupported", data.areFeaturesSupported(
+ SoftApCapability.SOFTAP_FEATURE_BAND_24G_SUPPORTED));
+ info.put("5gSupported", data.areFeaturesSupported(
+ SoftApCapability.SOFTAP_FEATURE_BAND_5G_SUPPORTED));
+ info.put("6gSupported", data.areFeaturesSupported(
+ SoftApCapability.SOFTAP_FEATURE_BAND_6G_SUPPORTED));
+ info.put("60gSupported", data.areFeaturesSupported(
+ SoftApCapability.SOFTAP_FEATURE_BAND_60G_SUPPORTED));
+ info.put("supported2GHzChannellist", build(
+ IntStream.of(data.getSupportedChannelList(SoftApConfiguration.BAND_2GHZ))
+ .boxed().toArray(Integer[]::new)));
+
+ info.put("supported5GHzChannellist", build(
+ IntStream.of(data.getSupportedChannelList(SoftApConfiguration.BAND_5GHZ))
+ .boxed().toArray(Integer[]::new)));
+ info.put("supported6GHzChannellist", build(
+ IntStream.of(data.getSupportedChannelList(SoftApConfiguration.BAND_6GHZ))
+ .boxed().toArray(Integer[]::new)));
+ info.put("supported60GHzChannellist", build(
+ IntStream.of(data.getSupportedChannelList(SoftApConfiguration.BAND_60GHZ))
+ .boxed().toArray(Integer[]::new)));
return info;
}
@@ -1231,6 +1341,11 @@
Log.d("build softAp info.");
info.put("frequency", data.getFrequency());
info.put("bandwidth", data.getBandwidth());
+ info.put("autoShutdownTimeoutMillis", data.getAutoShutdownTimeoutMillis());
+ if (SdkLevel.isAtLeastS()) {
+ info.put("wifiStandard", data.getWifiStandard());
+ info.put("bssid", data.getBssid());
+ }
return info;
}
diff --git a/ScriptingLayerForAndroid/Android.bp b/ScriptingLayerForAndroid/Android.bp
index 569cdcf..46797e7 100644
--- a/ScriptingLayerForAndroid/Android.bp
+++ b/ScriptingLayerForAndroid/Android.bp
@@ -66,6 +66,9 @@
},
jni_libs: ["libcom_googlecode_android_scripting_Exec"],
+
+ min_sdk_version: "30",
+ target_sdk_version: "31",
}
java_import {
diff --git a/ScriptingLayerForAndroid/AndroidManifest.xml b/ScriptingLayerForAndroid/AndroidManifest.xml
index c5f8ec6..4b19943 100644
--- a/ScriptingLayerForAndroid/AndroidManifest.xml
+++ b/ScriptingLayerForAndroid/AndroidManifest.xml
@@ -126,7 +126,7 @@
android:name=".Sl4aApplication"
android:theme="@android:style/Theme.DeviceDefault"
android:usesCleartextTraffic="true">
- <activity android:name=".activity.ScriptManager" android:configChanges="keyboardHidden|orientation" android:windowSoftInputMode="adjustResize" android:launchMode="singleTop">
+ <activity android:name=".activity.ScriptManager" android:configChanges="keyboardHidden|orientation" android:windowSoftInputMode="adjustResize" android:launchMode="singleTop" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@@ -136,7 +136,7 @@
</intent-filter>
<meta-data android:name="android.app.searchable" android:resource="@xml/searchable_scripts" />
</activity>
- <activity android:name=".activity.ScriptPicker" android:configChanges="keyboardHidden|orientation" android:label="Scripts">
+ <activity android:name=".activity.ScriptPicker" android:configChanges="keyboardHidden|orientation" android:label="Scripts" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.CREATE_SHORTCUT" />
<category android:name="android.intent.category.DEFAULT" />
@@ -147,31 +147,36 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
- <activity android:name=".activity.InterpreterPicker" android:configChanges="keyboardHidden|orientation" android:label="Interpreters">
+ <activity android:name=".activity.InterpreterPicker" android:configChanges="keyboardHidden|orientation" android:label="Interpreters"
+ android:exported="true">
<intent-filter>
<action android:name="android.intent.action.CREATE_SHORTCUT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
- <activity-alias android:name="LocalePlugin" android:targetActivity=".activity.ScriptPicker" android:label="@string/application_title" android:icon="@drawable/sl4a_logo_32">
+ <activity-alias android:name="LocalePlugin" android:targetActivity=".activity.ScriptPicker" android:label="@string/application_title" android:icon="@drawable/sl4a_logo_32"
+ android:exported="true">
<intent-filter>
<action android:name="com.twofortyfouram.locale.intent.action.EDIT_SETTING" />
</intent-filter>
</activity-alias>
- <receiver android:name=".locale.LocaleReceiver">
+ <receiver android:name=".locale.LocaleReceiver"
+ android:exported="true">
<intent-filter>
<action android:name="com.twofortyfouram.locale.intent.action.FIRE_SETTING" />
</intent-filter>
</receiver>
<activity android:name=".activity.Preferences" android:theme="@android:style/Theme.DeviceDefault.Settings" />
<activity android:name="org.connectbot.ConsoleActivity" android:theme="@android:style/Theme.DeviceDefault.NoActionBar" android:configChanges="keyboardHidden|orientation" android:windowSoftInputMode="stateAlwaysVisible|adjustResize" android:finishOnTaskLaunch="true" android:launchMode="singleTask" />
- <activity android:name=".activity.ScriptEditor" android:theme="@android:style/Theme.DeviceDefault.NoActionBar" android:configChanges="keyboardHidden|orientation" android:windowSoftInputMode="stateAlwaysVisible|adjustResize">
+ <activity android:name=".activity.ScriptEditor" android:theme="@android:style/Theme.DeviceDefault.NoActionBar" android:configChanges="keyboardHidden|orientation" android:windowSoftInputMode="stateAlwaysVisible|adjustResize"
+ android:exported="true">
<intent-filter>
<action android:name="com.googlecode.android_scripting.action.EDIT_SCRIPT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
- <activity android:name=".activity.ApiBrowser" android:configChanges="keyboardHidden|orientation" android:launchMode="singleTop" android:windowSoftInputMode="adjustResize">
+ <activity android:name=".activity.ApiBrowser" android:configChanges="keyboardHidden|orientation" android:launchMode="singleTop" android:windowSoftInputMode="adjustResize"
+ android:exported="true">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
@@ -180,7 +185,8 @@
<activity android:name=".activity.ApiPrompt" android:theme="@android:style/Theme.DeviceDefault.NoActionBar" android:configChanges="keyboardHidden|orientation" />
<activity android:name=".activity.TriggerManager" android:launchMode="singleTask" android:configChanges="keyboardHidden|orientation" />
<activity android:name=".activity.BluetoothDeviceList" android:configChanges="keyboardHidden|orientation" />
- <activity android:name=".activity.ScriptingLayerServiceLauncher" android:taskAffinity="" android:theme="@android:style/Theme.DeviceDefault.NoActionBar.TranslucentDecor">
+ <activity android:name=".activity.ScriptingLayerServiceLauncher" android:taskAffinity="" android:theme="@android:style/Theme.DeviceDefault.NoActionBar.TranslucentDecor"
+ android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
@@ -192,7 +198,8 @@
<service android:name=".service.ScriptingLayerService" />
<service android:name=".service.TriggerService" />
<service android:name="com.googlecode.android_scripting.facade.telephony.InCallServiceImpl"
- android:permission="android.permission.BIND_INCALL_SERVICE" >
+ android:permission="android.permission.BIND_INCALL_SERVICE"
+ android:exported="true">
<intent-filter>
<action android:name="android.telecom.InCallService"/>
</intent-filter>
@@ -204,14 +211,16 @@
<action android:name="com.googlecode.android_scripting.service.FacadeService.ACTION_BIND" />
</intent-filter>
</service>
- <service android:name=".facade.bluetooth.media.BluetoothSL4AAudioSrcMBS">
+ <service android:name=".facade.bluetooth.media.BluetoothSL4AAudioSrcMBS"
+ android:exported="true">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
<activity android:name=".activity.InterpreterManager" android:launchMode="singleTask" android:configChanges="keyboardHidden|orientation" />
<activity android:name=".activity.LogcatViewer" android:launchMode="singleTask" android:configChanges="keyboardHidden|orientation" />
- <activity android:name=".activity.ScriptsLiveFolder" android:label="Scripts" android:icon="@drawable/live_folder" android:configChanges="keyboardHidden|orientation">
+ <activity android:name=".activity.ScriptsLiveFolder" android:label="Scripts" android:icon="@drawable/live_folder" android:configChanges="keyboardHidden|orientation"
+ android:exported="true">
<intent-filter>
<action android:name="android.intent.action.CREATE_LIVE_FOLDER" />
<category android:name="android.intent.category.DEFAULT" />
@@ -233,7 +242,8 @@
</provider>
<uses-library android:name="android.test.runner" />
<activity android:name=".activity.ScriptProcessMonitor" android:launchMode="singleTask" android:finishOnTaskLaunch="true" />
- <activity android:configChanges="keyboardHidden|orientation" android:name="org.connectbot.util.ColorsActivity" android:theme="@android:style/Theme.DeviceDefault.Dialog">
+ <activity android:configChanges="keyboardHidden|orientation" android:name="org.connectbot.util.ColorsActivity" android:theme="@android:style/Theme.DeviceDefault.Dialog"
+ android:exported="true">
<intent-filter>
<action android:name="com.googlecode.android_scripting.PICK_TERMINAL_COLORS" />
<category android:name="android.intent.category.DEFAULT" />
diff --git a/ScriptingLayerForAndroid/src/com/googlecode/android_scripting/service/ScriptingLayerService.java b/ScriptingLayerForAndroid/src/com/googlecode/android_scripting/service/ScriptingLayerService.java
index ac6880a..154c3e5 100644
--- a/ScriptingLayerForAndroid/src/com/googlecode/android_scripting/service/ScriptingLayerService.java
+++ b/ScriptingLayerForAndroid/src/com/googlecode/android_scripting/service/ScriptingLayerService.java
@@ -120,7 +120,9 @@
protected Notification createNotification() {
Intent notificationIntent = new Intent(this, ScriptingLayerService.class);
notificationIntent.setAction(Constants.ACTION_SHOW_RUNNING_SCRIPTS);
- mNotificationPendingIntent = PendingIntent.getService(this, 0, notificationIntent, 0);
+ mNotificationPendingIntent =
+ PendingIntent.getService(this, 0, notificationIntent,
+ PendingIntent.FLAG_IMMUTABLE);
createNotificationChannel();
Notification.Builder builder = new Notification.Builder(this, CHANNEL_ID);