Merge "Add dplotnikov@ and gaillard@ as owners for Binder related files"
diff --git a/config/hiddenapi-force-blocked.txt b/boot/hiddenapi/hiddenapi-force-blocked.txt
similarity index 100%
rename from config/hiddenapi-force-blocked.txt
rename to boot/hiddenapi/hiddenapi-force-blocked.txt
diff --git a/config/hiddenapi-max-target-o.txt b/boot/hiddenapi/hiddenapi-max-target-o.txt
similarity index 100%
rename from config/hiddenapi-max-target-o.txt
rename to boot/hiddenapi/hiddenapi-max-target-o.txt
diff --git a/config/hiddenapi-max-target-p.txt b/boot/hiddenapi/hiddenapi-max-target-p.txt
similarity index 100%
rename from config/hiddenapi-max-target-p.txt
rename to boot/hiddenapi/hiddenapi-max-target-p.txt
diff --git a/config/hiddenapi-max-target-q.txt b/boot/hiddenapi/hiddenapi-max-target-q.txt
similarity index 100%
rename from config/hiddenapi-max-target-q.txt
rename to boot/hiddenapi/hiddenapi-max-target-q.txt
diff --git a/config/hiddenapi-max-target-r-loprio.txt b/boot/hiddenapi/hiddenapi-max-target-r-loprio.txt
similarity index 100%
rename from config/hiddenapi-max-target-r-loprio.txt
rename to boot/hiddenapi/hiddenapi-max-target-r-loprio.txt
diff --git a/config/hiddenapi-unsupported-packages.txt b/boot/hiddenapi/hiddenapi-unsupported-packages.txt
similarity index 100%
rename from config/hiddenapi-unsupported-packages.txt
rename to boot/hiddenapi/hiddenapi-unsupported-packages.txt
diff --git a/config/hiddenapi-unsupported.txt b/boot/hiddenapi/hiddenapi-unsupported.txt
similarity index 100%
rename from config/hiddenapi-unsupported.txt
rename to boot/hiddenapi/hiddenapi-unsupported.txt
diff --git a/core/api/current.txt b/core/api/current.txt
index b944ac9..5a2b8bd 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -33998,8 +33998,8 @@
public static final class SimPhonebookContract.SimRecords {
method @NonNull public static android.net.Uri getContentUri(int, int);
- method @WorkerThread public static int getEncodedNameLength(@NonNull android.content.ContentResolver, @NonNull String);
- method @NonNull public static android.net.Uri getItemUri(int, int, int);
+ method @IntRange(from=0) @WorkerThread public static int getEncodedNameLength(@NonNull android.content.ContentResolver, @NonNull String);
+ method @NonNull public static android.net.Uri getItemUri(int, int, @IntRange(from=1) int);
field public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/sim-contact_v2";
field public static final String CONTENT_TYPE = "vnd.android.cursor.dir/sim-contact_v2";
field public static final String ELEMENTARY_FILE_TYPE = "elementary_file_type";
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index eebf283..e31f174 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -6728,12 +6728,18 @@
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableSecureNfc(boolean);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn();
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOnSupported();
+ method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void registerControllerAlwaysOnStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.ControllerAlwaysOnStateCallback);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean removeNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler);
method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean setControllerAlwaysOn(boolean);
method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, int);
+ method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void unregisterControllerAlwaysOnStateCallback(@NonNull android.nfc.NfcAdapter.ControllerAlwaysOnStateCallback);
field public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 1; // 0x1
}
+ public static interface NfcAdapter.ControllerAlwaysOnStateCallback {
+ method public void onStateChanged(boolean);
+ }
+
public static interface NfcAdapter.NfcUnlockHandler {
method public boolean onUnlockAttempted(android.nfc.Tag);
}
diff --git a/core/java/android/hardware/hdmi/HdmiPlaybackClient.java b/core/java/android/hardware/hdmi/HdmiPlaybackClient.java
index f13326b..d06bc1d 100644
--- a/core/java/android/hardware/hdmi/HdmiPlaybackClient.java
+++ b/core/java/android/hardware/hdmi/HdmiPlaybackClient.java
@@ -84,7 +84,6 @@
* of the result
*/
public void oneTouchPlay(OneTouchPlayCallback callback) {
- // TODO: Use PendingResult.
try {
mService.oneTouchPlay(getCallbackWrapper(callback));
} catch (RemoteException e) {
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index da3febd..b074fad 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -772,6 +772,12 @@
return DebugUtils.flagsToString(NetworkPolicyManager.class, "BLOCKED_", blockedReasons);
}
+ /** @hide */
+ @NonNull
+ public static String allowedReasonsToString(int allowedReasons) {
+ return DebugUtils.flagsToString(NetworkPolicyManager.class, "ALLOWED_", allowedReasons);
+ }
+
/**
* Register a {@link NetworkPolicyCallback} to listen for changes to network blocked status
* of apps.
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index 11445e9..d5cc01a 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -24,6 +24,7 @@
import android.nfc.TechListParcel;
import android.nfc.IAppCallback;
import android.nfc.INfcAdapterExtras;
+import android.nfc.INfcControllerAlwaysOnStateCallback;
import android.nfc.INfcTag;
import android.nfc.INfcCardEmulation;
import android.nfc.INfcFCardEmulation;
@@ -75,4 +76,6 @@
boolean setControllerAlwaysOn(boolean value);
boolean isControllerAlwaysOn();
boolean isControllerAlwaysOnSupported();
+ void registerControllerAlwaysOnStateCallback(in INfcControllerAlwaysOnStateCallback callback);
+ void unregisterControllerAlwaysOnStateCallback(in INfcControllerAlwaysOnStateCallback callback);
}
diff --git a/core/java/android/nfc/INfcControllerAlwaysOnStateCallback.aidl b/core/java/android/nfc/INfcControllerAlwaysOnStateCallback.aidl
new file mode 100644
index 0000000..1e4fdd7
--- /dev/null
+++ b/core/java/android/nfc/INfcControllerAlwaysOnStateCallback.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 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.nfc;
+
+/**
+ * @hide
+ */
+oneway interface INfcControllerAlwaysOnStateCallback {
+ /**
+ * Called whenever the controller always on state changes
+ *
+ * @param isEnabled true if the state is enabled, false otherwise
+ */
+ void onControllerAlwaysOnStateChanged(boolean isEnabled);
+}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index eed2c77..bbf802c 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -16,6 +16,7 @@
package android.nfc;
+import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
@@ -47,6 +48,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.concurrent.Executor;
/**
* Represents the local NFC adapter.
@@ -65,6 +67,8 @@
public final class NfcAdapter {
static final String TAG = "NFC";
+ private final NfcControllerAlwaysOnStateListener mControllerAlwaysOnStateListener;
+
/**
* Intent to start an activity when a tag with NDEF payload is discovered.
*
@@ -350,22 +354,6 @@
"android.nfc.extra.HANDOVER_TRANSFER_STATUS";
/** @hide */
- public static final String ACTION_ALWAYS_ON_STATE_CHANGED =
- "android.nfc.action.ALWAYS_ON_STATE_CHANGED";
-
- /**
- * Used as an int extra field in {@link #ACTION_ALWAYS_ON_STATE_CHANGED}
- * intents to request the current power state. Possible values are:
- * {@link #STATE_OFF},
- * {@link #STATE_TURNING_ON},
- * {@link #STATE_ON},
- * {@link #STATE_TURNING_OFF},
- * @hide
- */
- public static final String EXTRA_ALWAYS_ON_STATE =
- "android.nfc.extra.ALWAYS_ON_STATE";
-
- /** @hide */
public static final int HANDOVER_TRANSFER_STATUS_SUCCESS = 0;
/** @hide */
public static final int HANDOVER_TRANSFER_STATUS_FAILURE = 1;
@@ -430,6 +418,22 @@
}
/**
+ * A callback to be invoked when NFC controller always on state changes.
+ * <p>Register your {@code ControllerAlwaysOnStateCallback} implementation with {@link
+ * NfcAdapter#registerControllerAlwaysOnStateCallback} and disable it with {@link
+ * NfcAdapter#unregisterControllerAlwaysOnStateCallback}.
+ * @see #registerControllerAlwaysOnStateCallback
+ * @hide
+ */
+ @SystemApi
+ public interface ControllerAlwaysOnStateCallback {
+ /**
+ * Called on NFC controller always on state changes
+ */
+ void onStateChanged(boolean isEnabled);
+ }
+
+ /**
* A callback to be invoked when the system successfully delivers your {@link NdefMessage}
* to another device.
* @see #setOnNdefPushCompleteCallback
@@ -744,6 +748,7 @@
mNfcUnlockHandlers = new HashMap<NfcUnlockHandler, INfcUnlockHandler>();
mTagRemovedListener = null;
mLock = new Object();
+ mControllerAlwaysOnStateListener = new NfcControllerAlwaysOnStateListener(getService());
}
/**
@@ -2239,14 +2244,16 @@
/**
* Sets NFC controller always on feature.
* <p>This API is for the NFCC internal state management. It allows to discriminate
- * the controller function from the NFC function by keeping the NFC Controller on without
+ * the controller function from the NFC function by keeping the NFC controller on without
* any NFC RF enabled if necessary.
- * <p>This call is asynchronous. Listen for {@link #ACTION_ALWAYS_ON_STATE_CHANGED}
- * broadcasts to find out when the operation is complete.
- * <p>If this returns true, then either NFCC is already on, or
- * a {@link #ACTION_ALWAYS_ON_STATE_CHANGED} broadcast will be sent to indicate
- * a state transition.
- * If this returns false, then there is some problem that prevents an attempt to turn NFCC on.
+ * <p>This call is asynchronous. Register a callback {@link #ControllerAlwaysOnStateCallback}
+ * by {@link #registerControllerAlwaysOnStateCallback} to find out when the operation is
+ * complete.
+ * <p>If this returns true, then either NFCC always on state has been set based on the value,
+ * or a {@link ControllerAlwaysOnStateCallback#onStateChanged(boolean)} will be invoked to
+ * indicate the state change.
+ * If this returns false, then there is some problem that prevents an attempt to turn NFCC
+ * always on.
* @param value if true the NFCC will be kept on (with no RF enabled if NFC adapter is
* disabled), if false the NFCC will follow completely the Nfc adapter state.
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
@@ -2284,7 +2291,6 @@
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
* @hide
*/
-
@SystemApi
@RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
public boolean isControllerAlwaysOn() {
@@ -2313,7 +2319,6 @@
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
* @hide
*/
-
@SystemApi
@RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
public boolean isControllerAlwaysOnSupported() {
@@ -2337,4 +2342,39 @@
return false;
}
}
+
+ /**
+ * Register a {@link ControllerAlwaysOnStateCallback} to listen for NFC controller always on
+ * state changes
+ * <p>The provided callback will be invoked by the given {@link Executor}.
+ *
+ * @param executor an {@link Executor} to execute given callback
+ * @param callback user implementation of the {@link ControllerAlwaysOnStateCallback}
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
+ public void registerControllerAlwaysOnStateCallback(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull ControllerAlwaysOnStateCallback callback) {
+ mControllerAlwaysOnStateListener.register(executor, callback);
+ }
+
+ /**
+ * Unregister the specified {@link ControllerAlwaysOnStateCallback}
+ * <p>The same {@link ControllerAlwaysOnStateCallback} object used when calling
+ * {@link #registerControllerAlwaysOnStateCallback(Executor, ControllerAlwaysOnStateCallback)}
+ * must be used.
+ *
+ * <p>Callbacks are automatically unregistered when application process goes away
+ *
+ * @param callback user implementation of the {@link ControllerAlwaysOnStateCallback}
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
+ public void unregisterControllerAlwaysOnStateCallback(
+ @NonNull ControllerAlwaysOnStateCallback callback) {
+ mControllerAlwaysOnStateListener.unregister(callback);
+ }
}
diff --git a/core/java/android/nfc/NfcControllerAlwaysOnStateListener.java b/core/java/android/nfc/NfcControllerAlwaysOnStateListener.java
new file mode 100644
index 0000000..69a9ec7
--- /dev/null
+++ b/core/java/android/nfc/NfcControllerAlwaysOnStateListener.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2021 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.nfc;
+
+import android.annotation.NonNull;
+import android.nfc.NfcAdapter.ControllerAlwaysOnStateCallback;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Executor;
+
+/**
+ * @hide
+ */
+public class NfcControllerAlwaysOnStateListener extends INfcControllerAlwaysOnStateCallback.Stub {
+ private static final String TAG = "NfcControllerAlwaysOnStateListener";
+
+ private final INfcAdapter mAdapter;
+
+ private final Map<ControllerAlwaysOnStateCallback, Executor> mCallbackMap = new HashMap<>();
+
+ private boolean mCurrentState = false;
+ private boolean mIsRegistered = false;
+
+ public NfcControllerAlwaysOnStateListener(@NonNull INfcAdapter adapter) {
+ mAdapter = adapter;
+ }
+
+ /**
+ * Register a {@link ControllerAlwaysOnStateCallback} with this
+ * {@link NfcControllerAlwaysOnStateListener}
+ *
+ * @param executor an {@link Executor} to execute given callback
+ * @param callback user implementation of the {@link ControllerAlwaysOnStateCallback}
+ */
+ public void register(@NonNull Executor executor,
+ @NonNull ControllerAlwaysOnStateCallback callback) {
+ synchronized (this) {
+ if (mCallbackMap.containsKey(callback)) {
+ return;
+ }
+
+ mCallbackMap.put(callback, executor);
+ if (!mIsRegistered) {
+ try {
+ mAdapter.registerControllerAlwaysOnStateCallback(this);
+ mIsRegistered = true;
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to register ControllerAlwaysOnStateListener");
+ }
+ }
+ }
+ }
+
+ /**
+ * Unregister the specified {@link ControllerAlwaysOnStateCallback}
+ *
+ * @param callback user implementation of the {@link ControllerAlwaysOnStateCallback}
+ */
+ public void unregister(@NonNull ControllerAlwaysOnStateCallback callback) {
+ synchronized (this) {
+ if (!mCallbackMap.containsKey(callback)) {
+ return;
+ }
+
+ mCallbackMap.remove(callback);
+
+ if (mCallbackMap.isEmpty() && mIsRegistered) {
+ try {
+ mAdapter.unregisterControllerAlwaysOnStateCallback(this);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to unregister ControllerAlwaysOnStateListener");
+ }
+ mIsRegistered = false;
+ }
+ }
+ }
+
+ private void sendCurrentState(@NonNull ControllerAlwaysOnStateCallback callback) {
+ synchronized (this) {
+ Executor executor = mCallbackMap.get(callback);
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> callback.onStateChanged(
+ mCurrentState));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
+ @Override
+ public void onControllerAlwaysOnStateChanged(boolean isEnabled) {
+ synchronized (this) {
+ mCurrentState = isEnabled;
+ for (ControllerAlwaysOnStateCallback cb : mCallbackMap.keySet()) {
+ sendCurrentState(cb);
+ }
+ }
+ }
+}
+
diff --git a/core/java/android/provider/SimPhonebookContract.java b/core/java/android/provider/SimPhonebookContract.java
index 030b863..fb89eb0 100644
--- a/core/java/android/provider/SimPhonebookContract.java
+++ b/core/java/android/provider/SimPhonebookContract.java
@@ -17,13 +17,14 @@
package android.provider;
import static android.provider.SimPhonebookContract.ElementaryFiles.EF_ADN;
-import static android.provider.SimPhonebookContract.ElementaryFiles.EF_ADN_PATH_SEGMENT;
import static android.provider.SimPhonebookContract.ElementaryFiles.EF_FDN;
-import static android.provider.SimPhonebookContract.ElementaryFiles.EF_FDN_PATH_SEGMENT;
import static android.provider.SimPhonebookContract.ElementaryFiles.EF_SDN;
-import static android.provider.SimPhonebookContract.ElementaryFiles.EF_SDN_PATH_SEGMENT;
+import static android.provider.SimPhonebookContract.ElementaryFiles.PATH_SEGMENT_EF_ADN;
+import static android.provider.SimPhonebookContract.ElementaryFiles.PATH_SEGMENT_EF_FDN;
+import static android.provider.SimPhonebookContract.ElementaryFiles.PATH_SEGMENT_EF_SDN;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.WorkerThread;
@@ -78,11 +79,11 @@
public static String getEfUriPath(@ElementaryFiles.EfType int efType) {
switch (efType) {
case EF_ADN:
- return EF_ADN_PATH_SEGMENT;
+ return PATH_SEGMENT_EF_ADN;
case EF_FDN:
- return EF_FDN_PATH_SEGMENT;
+ return PATH_SEGMENT_EF_FDN;
case EF_SDN:
- return EF_SDN_PATH_SEGMENT;
+ return PATH_SEGMENT_EF_SDN;
default:
throw new IllegalArgumentException("Unsupported EfType " + efType);
}
@@ -109,9 +110,9 @@
* the phone number can contain at most {@link ElementaryFiles#PHONE_NUMBER_MAX_LENGTH}
* characters. The {@link SimRecords#NAME} column can contain at most
* {@link ElementaryFiles#NAME_MAX_LENGTH} bytes when it is encoded for storage on the SIM.
- * Encoding is done internally and so the name should be provided unencoded but the number of
- * bytes required to encode it will vary depending on the characters it contains. This length
- * can be determined by calling
+ * Encoding is done internally and so the name should be provided to these provider APIs as a
+ * Java String but the number of bytes required to encode it for storage will vary depending on
+ * the characters it contains. This length can be determined by calling
* {@link SimRecords#getEncodedNameLength(ContentResolver, String)}.
* </p>
* <h3>Operations </h3>
@@ -308,7 +309,8 @@
*/
@NonNull
public static Uri getItemUri(
- int subscriptionId, @ElementaryFiles.EfType int efType, int recordNumber) {
+ int subscriptionId, @ElementaryFiles.EfType int efType,
+ @IntRange(from = 1) int recordNumber) {
// Elementary file record indices are 1-based.
Preconditions.checkArgument(recordNumber > 0, "Invalid recordNumber");
@@ -332,6 +334,7 @@
* @see ElementaryFiles#NAME_MAX_LENGTH
*/
@WorkerThread
+ @IntRange(from = 0)
public static int getEncodedNameLength(
@NonNull ContentResolver resolver, @NonNull String name) {
Objects.requireNonNull(name);
@@ -442,12 +445,27 @@
* methods operating on this Uri will throw UnsupportedOperationException
*/
public static final int EF_SDN = 3;
- /** @hide */
- public static final String EF_ADN_PATH_SEGMENT = "adn";
- /** @hide */
- public static final String EF_FDN_PATH_SEGMENT = "fdn";
- /** @hide */
- public static final String EF_SDN_PATH_SEGMENT = "sdn";
+ /**
+ * The Uri path segment used to target the ADN elementary file for SimPhonebookProvider
+ * content operations.
+ *
+ * @hide
+ */
+ public static final String PATH_SEGMENT_EF_ADN = "adn";
+ /**
+ * The Uri path segment used to target the FDN elementary file for SimPhonebookProvider
+ * content operations.
+ *
+ * @hide
+ */
+ public static final String PATH_SEGMENT_EF_FDN = "fdn";
+ /**
+ * The Uri path segment used to target the SDN elementary file for SimPhonebookProvider
+ * content operations.
+ *
+ * @hide
+ */
+ public static final String PATH_SEGMENT_EF_SDN = "sdn";
/** The MIME type of CONTENT_URI providing a directory of ADN-like elementary files. */
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/sim-elementary-file";
/** The MIME type of a CONTENT_URI subdirectory of a single ADN-like elementary file. */
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 1f7695e..24ade39 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -313,7 +313,6 @@
<protected-broadcast android:name="android.se.omapi.action.SECURE_ELEMENT_STATE_CHANGED" />
<protected-broadcast android:name="android.nfc.action.ADAPTER_STATE_CHANGED" />
- <protected-broadcast android:name="android.nfc.action.ALWAYS_ON_STATE_CHANGED" />
<protected-broadcast android:name="android.nfc.action.PREFERRED_PAYMENT_CHANGED" />
<protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" />
<protected-broadcast android:name="android.nfc.action.REQUIRE_UNLOCK_FOR_NFC" />
diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt
index f95d377..513b630 100644
--- a/packages/Connectivity/framework/api/module-lib-current.txt
+++ b/packages/Connectivity/framework/api/module-lib-current.txt
@@ -26,6 +26,9 @@
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void startCaptivePortalApp(@NonNull android.net.Network);
method public void systemReady();
+ field public static final String ACTION_PROMPT_LOST_VALIDATION = "android.net.action.PROMPT_LOST_VALIDATION";
+ field public static final String ACTION_PROMPT_PARTIAL_CONNECTIVITY = "android.net.action.PROMPT_PARTIAL_CONNECTIVITY";
+ field public static final String ACTION_PROMPT_UNVALIDATED = "android.net.action.PROMPT_UNVALIDATED";
field public static final int BLOCKED_METERED_REASON_ADMIN_DISABLED = 262144; // 0x40000
field public static final int BLOCKED_METERED_REASON_DATA_SAVER = 65536; // 0x10000
field public static final int BLOCKED_METERED_REASON_MASK = -65536; // 0xffff0000
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
index df222e6..84914a1 100644
--- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
+++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
@@ -425,7 +425,8 @@
*
* @hide
*/
- public static final String ACTION_PROMPT_UNVALIDATED = "android.net.conn.PROMPT_UNVALIDATED";
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final String ACTION_PROMPT_UNVALIDATED = "android.net.action.PROMPT_UNVALIDATED";
/**
* Action used to display a dialog that asks the user whether to avoid a network that is no
@@ -433,8 +434,9 @@
*
* @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
public static final String ACTION_PROMPT_LOST_VALIDATION =
- "android.net.conn.PROMPT_LOST_VALIDATION";
+ "android.net.action.PROMPT_LOST_VALIDATION";
/**
* Action used to display a dialog that asks the user whether to stay connected to a network
@@ -443,8 +445,9 @@
*
* @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
public static final String ACTION_PROMPT_PARTIAL_CONNECTIVITY =
- "android.net.conn.PROMPT_PARTIAL_CONNECTIVITY";
+ "android.net.action.PROMPT_PARTIAL_CONNECTIVITY";
/**
* Invalid tethering type.
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index 351e616..c6fdb9d 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -23,7 +23,6 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
-import android.os.FileUtils;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -45,6 +44,7 @@
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
@@ -131,13 +131,13 @@
private static final String FLASH_LOCK_UNLOCKED = "0";
private final Context mContext;
+ private final String mDataBlockFile;
private final boolean mIsRunningDSU;
private final Object mLock = new Object();
private final CountDownLatch mInitDoneSignal = new CountDownLatch(1);
private int mAllowedUid = -1;
private long mBlockDeviceSize;
- private String mDataBlockFile;
@GuardedBy("mLock")
private boolean mIsWritable = true;
@@ -145,8 +145,12 @@
public PersistentDataBlockService(Context context) {
super(context);
mContext = context;
- mDataBlockFile = SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP);
mIsRunningDSU = SystemProperties.getBoolean(GSI_RUNNING_PROP, false);
+ if (mIsRunningDSU) {
+ mDataBlockFile = GSI_SANDBOX;
+ } else {
+ mDataBlockFile = SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP);
+ }
mBlockDeviceSize = -1; // Load lazily
}
@@ -260,7 +264,11 @@
private long getBlockDeviceSize() {
synchronized (mLock) {
if (mBlockDeviceSize == -1) {
- mBlockDeviceSize = nativeGetBlockDeviceSize(mDataBlockFile);
+ if (mIsRunningDSU) {
+ mBlockDeviceSize = MAX_DATA_BLOCK_SIZE;
+ } else {
+ mBlockDeviceSize = nativeGetBlockDeviceSize(mDataBlockFile);
+ }
}
}
@@ -290,40 +298,30 @@
return true;
}
- private FileOutputStream getBlockOutputStream() throws IOException {
- if (!mIsRunningDSU) {
- return new FileOutputStream(new File(mDataBlockFile));
- } else {
- File sandbox = new File(GSI_SANDBOX);
- File realpdb = new File(SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP));
- if (!sandbox.exists()) {
- FileUtils.copy(realpdb, sandbox);
- mDataBlockFile = GSI_SANDBOX;
- }
- Slog.i(TAG, "PersistentDataBlock copy-on-write");
- return new FileOutputStream(sandbox);
- }
+ private FileChannel getBlockOutputChannel() throws IOException {
+ return new RandomAccessFile(mDataBlockFile, "rw").getChannel();
}
private boolean computeAndWriteDigestLocked() {
byte[] digest = computeDigestLocked(null);
if (digest != null) {
- DataOutputStream outputStream;
+ FileChannel channel;
try {
- outputStream = new DataOutputStream(getBlockOutputStream());
+ channel = getBlockOutputChannel();
} catch (IOException e) {
Slog.e(TAG, "partition not available?", e);
return false;
}
try {
- outputStream.write(digest, 0, DIGEST_SIZE_BYTES);
- outputStream.flush();
+ ByteBuffer buf = ByteBuffer.allocate(DIGEST_SIZE_BYTES);
+ buf.put(digest);
+ buf.flip();
+ channel.write(buf);
+ channel.force(true);
} catch (IOException e) {
Slog.e(TAG, "failed to write block checksum", e);
return false;
- } finally {
- IoUtils.closeQuietly(outputStream);
}
return true;
} else {
@@ -374,25 +372,18 @@
}
private void formatPartitionLocked(boolean setOemUnlockEnabled) {
- DataOutputStream outputStream;
- try {
- outputStream = new DataOutputStream(getBlockOutputStream());
- } catch (IOException e) {
- Slog.e(TAG, "partition not available?", e);
- return;
- }
- byte[] data = new byte[DIGEST_SIZE_BYTES];
try {
- outputStream.write(data, 0, DIGEST_SIZE_BYTES);
- outputStream.writeInt(PARTITION_TYPE_MARKER);
- outputStream.writeInt(0); // data size
- outputStream.flush();
+ FileChannel channel = getBlockOutputChannel();
+ ByteBuffer buf = ByteBuffer.allocate(DIGEST_SIZE_BYTES + HEADER_SIZE);
+ buf.put(new byte[DIGEST_SIZE_BYTES]);
+ buf.putInt(PARTITION_TYPE_MARKER);
+ buf.putInt(0);
+ channel.write(buf);
+ channel.force(true);
} catch (IOException e) {
Slog.e(TAG, "failed to format block", e);
return;
- } finally {
- IoUtils.closeQuietly(outputStream);
}
doSetOemUnlockEnabledLocked(setOemUnlockEnabled);
@@ -400,16 +391,9 @@
}
private void doSetOemUnlockEnabledLocked(boolean enabled) {
- FileOutputStream outputStream;
- try {
- outputStream = getBlockOutputStream();
- } catch (IOException e) {
- Slog.e(TAG, "partition not available", e);
- return;
- }
try {
- FileChannel channel = outputStream.getChannel();
+ FileChannel channel = getBlockOutputChannel();
channel.position(getBlockDeviceSize() - 1);
@@ -417,13 +401,12 @@
data.put(enabled ? (byte) 1 : (byte) 0);
data.flip();
channel.write(data);
- outputStream.flush();
+ channel.force(true);
} catch (IOException e) {
Slog.e(TAG, "unable to access persistent partition", e);
return;
} finally {
SystemProperties.set(OEM_UNLOCK_PROP, enabled ? "1" : "0");
- IoUtils.closeQuietly(outputStream);
}
}
@@ -477,35 +460,32 @@
return (int) -maxBlockSize;
}
- DataOutputStream outputStream;
+ FileChannel channel;
try {
- outputStream = new DataOutputStream(getBlockOutputStream());
+ channel = getBlockOutputChannel();
} catch (IOException e) {
Slog.e(TAG, "partition not available?", e);
- return -1;
+ return -1;
}
- ByteBuffer headerAndData = ByteBuffer.allocate(data.length + HEADER_SIZE);
+ ByteBuffer headerAndData = ByteBuffer.allocate(
+ data.length + HEADER_SIZE + DIGEST_SIZE_BYTES);
+ headerAndData.put(new byte[DIGEST_SIZE_BYTES]);
headerAndData.putInt(PARTITION_TYPE_MARKER);
headerAndData.putInt(data.length);
headerAndData.put(data);
-
+ headerAndData.flip();
synchronized (mLock) {
if (!mIsWritable) {
- IoUtils.closeQuietly(outputStream);
return -1;
}
try {
- byte[] checksum = new byte[DIGEST_SIZE_BYTES];
- outputStream.write(checksum, 0, DIGEST_SIZE_BYTES);
- outputStream.write(headerAndData.array());
- outputStream.flush();
+ channel.write(headerAndData);
+ channel.force(true);
} catch (IOException e) {
Slog.e(TAG, "failed writing to the persistent data block", e);
return -1;
- } finally {
- IoUtils.closeQuietly(outputStream);
}
if (computeAndWriteDigestLocked()) {
@@ -565,17 +545,6 @@
public void wipe() {
enforceOemUnlockWritePermission();
- if (mIsRunningDSU) {
- File sandbox = new File(GSI_SANDBOX);
- if (sandbox.exists()) {
- if (sandbox.delete()) {
- mDataBlockFile = SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP);
- } else {
- Slog.e(TAG, "Failed to wipe sandbox persistent data block");
- }
- }
- return;
- }
synchronized (mLock) {
int ret = nativeWipe(mDataBlockFile);
@@ -733,28 +702,18 @@
}
private void writeDataBuffer(long offset, ByteBuffer dataBuffer) {
- FileOutputStream outputStream;
- try {
- outputStream = getBlockOutputStream();
- } catch (IOException e) {
- Slog.e(TAG, "partition not available", e);
- return;
- }
synchronized (mLock) {
if (!mIsWritable) {
- IoUtils.closeQuietly(outputStream);
return;
}
try {
- FileChannel channel = outputStream.getChannel();
+ FileChannel channel = getBlockOutputChannel();
channel.position(offset);
channel.write(dataBuffer);
- outputStream.flush();
+ channel.force(true);
} catch (IOException e) {
Slog.e(TAG, "unable to access persistent partition", e);
return;
- } finally {
- IoUtils.closeQuietly(outputStream);
}
computeAndWriteDigestLocked();
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
index 470a25b..3d1a49e 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java
@@ -201,7 +201,6 @@
// Only source devices that react to routing control messages should implement
// this method (e.g. a TV with built in switch).
- // TODO(): decide which type will handle the routing when multi device type is supported
protected void handleRoutingChangeAndInformation(int physicalAddress, HdmiCecMessage message) {
// do nothing
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 290307b..319800d 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -5857,7 +5857,8 @@
return (bundle != null) ? bundle.getBoolean(key, defaultValue) : defaultValue;
}
- private class UidBlockedState {
+ @VisibleForTesting
+ static final class UidBlockedState {
public int blockedReasons;
public int allowedReasons;
public int effectiveBlockedReasons;
@@ -5869,16 +5870,21 @@
}
void updateEffectiveBlockedReasons() {
- effectiveBlockedReasons = blockedReasons;
+ effectiveBlockedReasons = getEffectiveBlockedReasons(blockedReasons, allowedReasons);
+ }
+
+ @VisibleForTesting
+ static int getEffectiveBlockedReasons(int blockedReasons, int allowedReasons) {
+ int effectiveBlockedReasons = blockedReasons;
// If the uid is not subject to any blocked reasons, then return early
if (blockedReasons == BLOCKED_REASON_NONE) {
- return;
+ return effectiveBlockedReasons;
}
if ((allowedReasons & ALLOWED_REASON_SYSTEM) != 0) {
- effectiveBlockedReasons = (blockedReasons & ALLOWED_METERED_REASON_MASK);
+ effectiveBlockedReasons &= ALLOWED_METERED_REASON_MASK;
}
if ((allowedReasons & ALLOWED_METERED_REASON_SYSTEM) != 0) {
- effectiveBlockedReasons = (blockedReasons & ~ALLOWED_METERED_REASON_MASK);
+ effectiveBlockedReasons &= ~ALLOWED_METERED_REASON_MASK;
}
if ((allowedReasons & ALLOWED_REASON_FOREGROUND) != 0) {
effectiveBlockedReasons &= ~BLOCKED_REASON_BATTERY_SAVER;
@@ -5904,6 +5910,7 @@
if ((allowedReasons & ALLOWED_METERED_REASON_USER_EXEMPTED) != 0) {
effectiveBlockedReasons &= ~BLOCKED_METERED_REASON_DATA_SAVER;
}
+ return effectiveBlockedReasons;
}
}
diff --git a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
index 13798ba..d67796b 100644
--- a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
+++ b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
@@ -128,18 +128,12 @@
private static final Map<String, Integer> ISA_MAP = new HashMap();
static {
- COMPILE_FILTER_MAP.put("arm", ArtStatsLog.
- ART_DATUM_REPORTED__ISA__ART_ISA_ARM);
- COMPILE_FILTER_MAP.put("arm64", ArtStatsLog.
- ART_DATUM_REPORTED__ISA__ART_ISA_ARM64);
- COMPILE_FILTER_MAP.put("x86", ArtStatsLog.
- ART_DATUM_REPORTED__ISA__ART_ISA_X86);
- COMPILE_FILTER_MAP.put("x86_64", ArtStatsLog.
- ART_DATUM_REPORTED__ISA__ART_ISA_X86_64);
- COMPILE_FILTER_MAP.put("mips", ArtStatsLog.
- ART_DATUM_REPORTED__ISA__ART_ISA_MIPS);
- COMPILE_FILTER_MAP.put("mips64", ArtStatsLog.
- ART_DATUM_REPORTED__ISA__ART_ISA_MIPS64);
+ ISA_MAP.put("arm", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_ARM);
+ ISA_MAP.put("arm64", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_ARM64);
+ ISA_MAP.put("x86", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_X86);
+ ISA_MAP.put("x86_64", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_X86_64);
+ ISA_MAP.put("mips", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_MIPS);
+ ISA_MAP.put("mips64", ArtStatsLog.ART_DATUM_REPORTED__ISA__ART_ISA_MIPS64);
}
public static void writeStatsLog(
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 24bb1b1..d0bd8b3 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -102,6 +102,7 @@
"libaudioclient",
"libbase",
"libappfuse",
+ "libbinder_ndk",
"libbinder",
"libcutils",
"libcrypto",
@@ -110,6 +111,7 @@
"libhardware",
"libhardware_legacy",
"libhidlbase",
+ "libmemtrackproxy",
"libmtp",
"libnativehelper",
"libprocessgroup",
@@ -154,6 +156,7 @@
"android.hardware.input.classifier@1.0",
"android.hardware.ir@1.0",
"android.hardware.light@2.0",
+ "android.hardware.memtrack-V1-ndk_platform",
"android.hardware.power@1.0",
"android.hardware.power@1.1",
"android.hardware.power-V1-cpp",
diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp
index d18043f..b93b8ab 100644
--- a/services/core/jni/com_android_server_SystemServer.cpp
+++ b/services/core/jni/com_android_server_SystemServer.cpp
@@ -23,11 +23,14 @@
#include <jni.h>
#include <nativehelper/JNIHelp.h>
+#include <android/binder_manager.h>
+#include <android/binder_stability.h>
#include <android/hidl/manager/1.2/IServiceManager.h>
#include <binder/IServiceManager.h>
#include <hidl/HidlTransportSupport.h>
#include <incremental_service.h>
+#include <memtrackproxy/MemtrackProxy.h>
#include <schedulerservice/SchedulingPolicyService.h>
#include <sensorservice/SensorService.h>
#include <sensorservicehidl/SensorManager.h>
@@ -57,6 +60,21 @@
}
+static void android_server_SystemServer_startMemtrackProxyService(JNIEnv* env,
+ jobject /* clazz */) {
+ using aidl::android::hardware::memtrack::MemtrackProxy;
+
+ const char* memtrackProxyService = "memtrack.proxy";
+
+ std::shared_ptr<MemtrackProxy> memtrack_proxy = ndk::SharedRefBase::make<MemtrackProxy>();
+ auto binder = memtrack_proxy->asBinder();
+
+ AIBinder_forceDowngradeToLocalStability(binder.get());
+
+ const binder_exception_t err = AServiceManager_addService(binder.get(), memtrackProxyService);
+ LOG_ALWAYS_FATAL_IF(err != EX_NONE, "Cannot register %s: %d", memtrackProxyService, err);
+}
+
static void android_server_SystemServer_startHidlServices(JNIEnv* env, jobject /* clazz */) {
using ::android::frameworks::schedulerservice::V1_0::ISchedulingPolicyService;
using ::android::frameworks::schedulerservice::V1_0::implementation::SchedulingPolicyService;
@@ -121,6 +139,8 @@
static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{"startSensorService", "()V", (void*)android_server_SystemServer_startSensorService},
+ {"startMemtrackProxyService", "()V",
+ (void*)android_server_SystemServer_startMemtrackProxyService},
{"startHidlServices", "()V", (void*)android_server_SystemServer_startHidlServices},
{"initZygoteChildHeapProfiling", "()V",
(void*)android_server_SystemServer_initZygoteChildHeapProfiling},
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 80f43d7..81ec8f4 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -393,6 +393,11 @@
private static native void startSensorService();
/**
+ * Start the memtrack proxy service.
+ */
+ private static native void startMemtrackProxyService();
+
+ /**
* Start all HIDL services that are run inside the system server. This may take some time.
*/
private static native void startHidlServices();
@@ -830,6 +835,12 @@
mSystemServiceManager.startService(UriGrantsManagerService.Lifecycle.class);
t.traceEnd();
+ // Start MemtrackProxyService before ActivityManager, so that early calls
+ // to Memtrack::getMemory() don't fail.
+ t.traceBegin("MemtrackProxyService");
+ startMemtrackProxyService();
+ t.traceEnd();
+
// Activity manager runs the show.
t.traceBegin("StartActivityManager");
// TODO: Might need to move after migration to WM.
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index f5876fa..e9e2486 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -18,6 +18,12 @@
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
import static android.Manifest.permission.NETWORK_STACK;
+import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER;
+import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED;
+import static android.net.ConnectivityManager.BLOCKED_REASON_APP_STANDBY;
+import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER;
+import static android.net.ConnectivityManager.BLOCKED_REASON_DOZE;
+import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
@@ -29,10 +35,17 @@
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.SNOOZE_NEVER;
import static android.net.NetworkPolicy.WARNING_DISABLED;
+import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_FOREGROUND;
+import static android.net.NetworkPolicyManager.ALLOWED_METERED_REASON_SYSTEM;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_FOREGROUND;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_NONE;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_SYSTEM;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
+import static android.net.NetworkPolicyManager.allowedReasonsToString;
+import static android.net.NetworkPolicyManager.blockedReasonsToString;
import static android.net.NetworkPolicyManager.uidPoliciesToString;
import static android.net.NetworkPolicyManager.uidRulesToString;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
@@ -59,6 +72,7 @@
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_RAPID;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING;
+import static com.android.server.net.NetworkPolicyManagerService.UidBlockedState.getEffectiveBlockedReasons;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -134,8 +148,10 @@
import android.util.ArrayMap;
import android.util.DataUnit;
import android.util.Log;
+import android.util.Pair;
import android.util.Range;
import android.util.RecurrenceRule;
+import android.util.SparseArray;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.FlakyTest;
@@ -1896,6 +1912,65 @@
assertFalse(mService.isUidNetworkingBlocked(UID_E, false));
}
+ @Test
+ public void testUpdateEffectiveBlockedReasons() {
+ final SparseArray<Pair<Integer, Integer>> effectiveBlockedReasons = new SparseArray<>();
+ effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
+ Pair.create(BLOCKED_REASON_NONE, ALLOWED_REASON_NONE));
+
+ effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
+ Pair.create(BLOCKED_REASON_BATTERY_SAVER, ALLOWED_REASON_SYSTEM));
+ effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
+ Pair.create(BLOCKED_REASON_BATTERY_SAVER | BLOCKED_REASON_DOZE,
+ ALLOWED_REASON_SYSTEM));
+ effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
+ Pair.create(BLOCKED_METERED_REASON_DATA_SAVER,
+ ALLOWED_METERED_REASON_SYSTEM));
+ effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
+ Pair.create(BLOCKED_METERED_REASON_DATA_SAVER
+ | BLOCKED_METERED_REASON_USER_RESTRICTED,
+ ALLOWED_METERED_REASON_SYSTEM));
+
+ effectiveBlockedReasons.put(BLOCKED_METERED_REASON_DATA_SAVER,
+ Pair.create(BLOCKED_REASON_BATTERY_SAVER | BLOCKED_METERED_REASON_DATA_SAVER,
+ ALLOWED_REASON_SYSTEM));
+ effectiveBlockedReasons.put(BLOCKED_REASON_APP_STANDBY,
+ Pair.create(BLOCKED_REASON_APP_STANDBY | BLOCKED_METERED_REASON_USER_RESTRICTED,
+ ALLOWED_METERED_REASON_SYSTEM));
+
+ effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
+ Pair.create(BLOCKED_REASON_BATTERY_SAVER, ALLOWED_REASON_FOREGROUND));
+ effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
+ Pair.create(BLOCKED_REASON_BATTERY_SAVER | BLOCKED_REASON_DOZE,
+ ALLOWED_REASON_FOREGROUND));
+ effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
+ Pair.create(BLOCKED_METERED_REASON_DATA_SAVER, ALLOWED_METERED_REASON_FOREGROUND));
+ effectiveBlockedReasons.put(BLOCKED_REASON_NONE,
+ Pair.create(BLOCKED_METERED_REASON_DATA_SAVER
+ | BLOCKED_METERED_REASON_USER_RESTRICTED,
+ ALLOWED_METERED_REASON_FOREGROUND));
+ effectiveBlockedReasons.put(BLOCKED_METERED_REASON_DATA_SAVER,
+ Pair.create(BLOCKED_REASON_BATTERY_SAVER | BLOCKED_METERED_REASON_DATA_SAVER,
+ ALLOWED_REASON_FOREGROUND));
+ effectiveBlockedReasons.put(BLOCKED_REASON_BATTERY_SAVER,
+ Pair.create(BLOCKED_REASON_BATTERY_SAVER
+ | BLOCKED_METERED_REASON_USER_RESTRICTED,
+ ALLOWED_METERED_REASON_FOREGROUND));
+ // TODO: test more combinations of blocked reasons.
+
+ for (int i = 0; i < effectiveBlockedReasons.size(); ++i) {
+ final int expectedEffectiveBlockedReasons = effectiveBlockedReasons.keyAt(i);
+ final int blockedReasons = effectiveBlockedReasons.valueAt(i).first;
+ final int allowedReasons = effectiveBlockedReasons.valueAt(i).second;
+ final String errorMsg = "Expected="
+ + blockedReasonsToString(expectedEffectiveBlockedReasons)
+ + "; blockedReasons=" + blockedReasonsToString(blockedReasons)
+ + ", allowedReasons=" + allowedReasonsToString(allowedReasons);
+ assertEquals(errorMsg, expectedEffectiveBlockedReasons,
+ getEffectiveBlockedReasons(blockedReasons, allowedReasons));
+ }
+ }
+
private String formatBlockedStateError(int uid, int rule, boolean metered,
boolean backgroundRestricted) {
return String.format(
diff --git a/tools/hiddenapi/OWNERS b/tools/hiddenapi/OWNERS
new file mode 100644
index 0000000..afbeef5
--- /dev/null
+++ b/tools/hiddenapi/OWNERS
@@ -0,0 +1,7 @@
+# compat-team@ for changes to hiddenapi files
+andreionea@google.com
+mathewi@google.com
+satayev@google.com
+
+# soong-team@ as the files these tools protect are tightly coupled with Soong
+file:platform/build/soong:/OWNERS
diff --git a/tools/hiddenapi/exclude.sh b/tools/hiddenapi/exclude.sh
index 73eacc0..2924e01 100755
--- a/tools/hiddenapi/exclude.sh
+++ b/tools/hiddenapi/exclude.sh
@@ -7,11 +7,9 @@
# the team email to use in the event of this detecting an entry in a <team> package. Also
# add <team> to the TEAMS list.
LIBCORE_PACKAGES="\
- android.icu \
android.system \
android.test \
com.android.bouncycastle \
- com.android.conscrypt \
com.android.i18n.phonenumbers \
com.android.okhttp \
com.sun \
@@ -24,37 +22,54 @@
org.json \
org.w3c.dom \
org.xml.sax \
+ org.xmlpull.v1 \
sun \
"
LIBCORE_EMAIL=libcore-team@android.com
+I18N_PACKAGES="\
+ android.icu \
+ "
+
+I18N_EMAIL=$LIBCORE_EMAIL
+
+CONSCRYPT_PACKAGES="\
+ com.android.org.conscrypt \
+ "
+
+CONSCRYPT_EMAIL=$LIBCORE_EMAIL
+
# List of teams.
-TEAMS=LIBCORE
+TEAMS="LIBCORE I18N CONSCRYPT"
+
+SHA=$1
# Generate the list of packages and convert to a regular expression.
PACKAGES=$(for t in $TEAMS; do echo $(eval echo \${${t}_PACKAGES}); done)
RE=$(echo ${PACKAGES} | sed "s/ /|/g")
-git show --name-only --pretty=format: $1 | grep "config/hiddenapi-.*txt" | while read file; do
- ENTRIES=$(grep -E "^L(${RE})/" || true <(git show $1:$file))
+EXIT_CODE=0
+for file in $(git show --name-only --pretty=format: $SHA | grep "config/hiddenapi-.*txt"); do
+ ENTRIES=$(grep -E "^\+L(${RE})/" <(git diff ${SHA}~1 ${SHA} $file) | sed "s|^\+||" || echo)
if [[ -n "${ENTRIES}" ]]; then
- echo -e "\e[1m\e[31m$file $1 contains the following entries\e[0m"
+ echo -e "\e[1m\e[31m$file $SHA contains the following entries\e[0m"
echo -e "\e[1m\e[31mfor packages that are handled using UnsupportedAppUsage. Please remove\e[0m"
echo -e "\e[1m\e[31mthese entries and add annotations instead.\e[0m"
# Partition the entries by team and provide contact details to aid in fixing the issue.
for t in ${TEAMS}
do
PACKAGES=$(eval echo \${${t}_PACKAGES})
- RE=$(echo ${PACKAGES} | sed "s/ /|/g")
- TEAM_ENTRIES=$(grep -E "^L(${RE})/" <(echo "${ENTRIES}"))
+ TEAM_RE=$(echo ${PACKAGES} | sed "s/ /|/g")
+ TEAM_ENTRIES=$(grep -E "^L(${TEAM_RE})/" <(echo "${ENTRIES}") || echo)
if [[ -n "${TEAM_ENTRIES}" ]]; then
EMAIL=$(eval echo \${${t}_EMAIL})
- echo -e "\e[33mContact ${EMAIL} or compat- for help with the following:\e[0m"
- for i in ${ENTRIES}
+ echo -e "\e[33mContact ${EMAIL} for help with the following:\e[0m"
+ for i in ${TEAM_ENTRIES}
do
echo -e "\e[33m ${i}\e[0m"
done
fi
done
- exit 1
+ EXIT_CODE=1
fi
done
+exit $EXIT_CODE