summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ActivityThread.java21
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp13
-rw-r--r--libs/WindowManager/Shell/OWNERS2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OWNERS1
-rw-r--r--media/java/android/media/MediaCas.java2
-rw-r--r--media/java/android/media/MediaFormat.java2
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java1
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java12
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java1
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java8
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java21
-rw-r--r--services/core/java/com/android/server/locksettings/RebootEscrowManager.java12
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerShellCommand.java28
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java76
-rw-r--r--telecomm/java/android/telecom/Connection.java2
-rw-r--r--telephony/java/android/telephony/ServiceState.java30
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java41
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java38
-rw-r--r--telephony/java/com/android/internal/telephony/ISub.aidl5
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl7
-rw-r--r--tests/EnforcePermission/Android.bp22
-rw-r--r--tests/EnforcePermission/aidl/android/tests/enforcepermission/INested.aidl25
-rw-r--r--tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl34
-rw-r--r--tests/EnforcePermission/service-app/Android.bp32
-rw-r--r--tests/EnforcePermission/service-app/AndroidManifest.xml27
-rw-r--r--tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java48
-rw-r--r--tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java119
-rw-r--r--tests/EnforcePermission/test-app/Android.bp38
-rw-r--r--tests/EnforcePermission/test-app/AndroidManifest.xml32
-rw-r--r--tests/EnforcePermission/test-app/AndroidTest.xml28
-rw-r--r--tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java129
31 files changed, 723 insertions, 134 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index e709a1ac2d36..30a2303a5e41 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3434,8 +3434,13 @@ public final class ActivityThread extends ClientTransactionHandler
if (mLastProcessState == processState) {
return;
}
+ // Do not issue a transitional GC if we are transitioning between 2 cached states.
+ // Only update if the state flips between cached and uncached or vice versa
+ if (ActivityManager.isProcStateCached(mLastProcessState)
+ != ActivityManager.isProcStateCached(processState)) {
+ updateVmProcessState(processState);
+ }
mLastProcessState = processState;
- updateVmProcessState(processState);
if (localLOGV) {
Slog.i(TAG, "******************* PROCESS STATE CHANGED TO: " + processState
+ (fromIpc ? " (from ipc" : ""));
@@ -3444,12 +3449,16 @@ public final class ActivityThread extends ClientTransactionHandler
}
/** Update VM state based on ActivityManager.PROCESS_STATE_* constants. */
+ // Currently ART VM only uses state updates for Transitional GC, and thus
+ // this function initiates a Transitional GC for transitions into Cached apps states.
private void updateVmProcessState(int processState) {
- // TODO: Tune this since things like gmail sync are important background but not jank
- // perceptible.
- final int state = processState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
- ? VM_PROCESS_STATE_JANK_PERCEPTIBLE
- : VM_PROCESS_STATE_JANK_IMPERCEPTIBLE;
+ // Only a transition into Cached state should result in a Transitional GC request
+ // to the ART runtime. Update VM state to JANK_IMPERCEPTIBLE in that case.
+ // Note that there are 4 possible cached states currently, all of which are
+ // JANK_IMPERCEPTIBLE from GC point of view.
+ final int state = ActivityManager.isProcStateCached(processState)
+ ? VM_PROCESS_STATE_JANK_IMPERCEPTIBLE
+ : VM_PROCESS_STATE_JANK_PERCEPTIBLE;
VMRuntime.getRuntime().updateProcessState(state);
}
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index fad9e0e79899..42255bf3793e 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1799,10 +1799,15 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
if (!is_system_server && getuid() == 0) {
const int rc = createProcessGroup(uid, getpid());
if (rc != 0) {
- fail_fn(rc == -EROFS ? CREATE_ERROR("createProcessGroup failed, kernel missing "
- "CONFIG_CGROUP_CPUACCT?")
- : CREATE_ERROR("createProcessGroup(%d, %d) failed: %s", uid,
- /* pid= */ 0, strerror(-rc)));
+ if (rc == -ESRCH) {
+ // If process is dead, treat this as a non-fatal error
+ ALOGE("createProcessGroup(%d, %d) failed: %s", uid, /* pid= */ 0, strerror(-rc));
+ } else {
+ fail_fn(rc == -EROFS ? CREATE_ERROR("createProcessGroup failed, kernel missing "
+ "CONFIG_CGROUP_CPUACCT?")
+ : CREATE_ERROR("createProcessGroup(%d, %d) failed: %s", uid,
+ /* pid= */ 0, strerror(-rc)));
+ }
}
}
diff --git a/libs/WindowManager/Shell/OWNERS b/libs/WindowManager/Shell/OWNERS
index 4b125904004a..852edef544b8 100644
--- a/libs/WindowManager/Shell/OWNERS
+++ b/libs/WindowManager/Shell/OWNERS
@@ -1,4 +1,4 @@
xutan@google.com
# Give submodule owners in shell resource approval
-per-file res*/*/*.xml = hwwang@google.com, lbill@google.com, madym@google.com
+per-file res*/*/*.xml = hwwang@google.com, jorgegil@google.com, lbill@google.com, madym@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OWNERS
new file mode 100644
index 000000000000..4417209b85ed
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/OWNERS
@@ -0,0 +1 @@
+jorgegil@google.com
diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java
index 0704da4fb63d..c74490027e1d 100644
--- a/media/java/android/media/MediaCas.java
+++ b/media/java/android/media/MediaCas.java
@@ -436,7 +436,7 @@ public final class MediaCas implements AutoCloseable {
if (mEventHandler != null) {
mEventHandler.sendMessage(
mEventHandler.obtainMessage(
- EventHandler.MSG_CAS_EVENT, event, arg, data));
+ EventHandler.MSG_CAS_EVENT, event, arg, toBytes(data)));
}
}
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index b51c018e3ca0..c33d206b77f7 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -1171,7 +1171,7 @@ public final class MediaFormat {
/**
* A key describing the desired bitrate mode to be used by an encoder.
- * Constants are declared in {@link MediaCodecInfo.CodecCapabilities}.
+ * Constants are declared in {@link MediaCodecInfo.EncoderCapabilities}.
*
* @see MediaCodecInfo.EncoderCapabilities#isBitrateModeSupported(int)
*/
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
index 162bb2c720e8..b8887ae872d5 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
@@ -49,6 +49,7 @@ public class GlobalSettings {
Settings.Global.CHARGING_SOUNDS_ENABLED,
Settings.Global.USB_MASS_STORAGE_ENABLED,
Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+ Settings.Global.NETWORK_AVOID_BAD_WIFI,
Settings.Global.WIFI_WAKEUP_ENABLED,
Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
Settings.Global.USE_OPEN_WIFI_PACKAGE,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index fbbdd32c5886..3bb76d20be10 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -17,6 +17,9 @@
package android.provider.settings.validators;
import static android.media.AudioFormat.SURROUND_SOUND_ENCODING;
+import static android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI_AVOID;
+import static android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI_IGNORE;
+import static android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI_PROMPT;
import static android.provider.settings.validators.SettingsValidators.ANY_INTEGER_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.ANY_STRING_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.BOOLEAN_VALIDATOR;
@@ -95,6 +98,14 @@ public class GlobalSettingsValidators {
VALIDATORS.put(
Global.NETWORK_RECOMMENDATIONS_ENABLED,
new DiscreteValueValidator(new String[] {"-1", "0", "1"}));
+ VALIDATORS.put(
+ Global.NETWORK_AVOID_BAD_WIFI,
+ new DiscreteValueValidator(
+ new String[] {
+ String.valueOf(NETWORK_AVOID_BAD_WIFI_IGNORE),
+ String.valueOf(NETWORK_AVOID_BAD_WIFI_PROMPT),
+ String.valueOf(NETWORK_AVOID_BAD_WIFI_AVOID),
+ }));
VALIDATORS.put(Global.WIFI_WAKEUP_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, BOOLEAN_VALIDATOR);
VALIDATORS.put(
@@ -338,4 +349,3 @@ public class GlobalSettingsValidators {
VALIDATORS.put(Global.Wearable.COOLDOWN_MODE_ON, BOOLEAN_VALIDATOR);
}
}
-
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index ce670d4d2162..2670852b7533 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -374,7 +374,6 @@ public class SettingsBackupTest {
Settings.Global.NETPOLICY_QUOTA_FRAC_JOBS,
Settings.Global.NETPOLICY_QUOTA_FRAC_MULTIPATH,
Settings.Global.NETPOLICY_OVERRIDE_ENABLED,
- Settings.Global.NETWORK_AVOID_BAD_WIFI,
Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES,
Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE,
Settings.Global.NETWORK_WATCHLIST_LAST_REPORT_TIME,
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 73d9cc759b10..2aa93783c501 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -1483,6 +1483,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
public void setFirewallUidRules(int chain, int[] uids, int[] rules) {
enforceSystemUid();
synchronized (mQuotaLock) {
+ final int[] applicableUidsForChain;
synchronized (mRulesLock) {
SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
SparseIntArray newRules = new SparseIntArray();
@@ -1506,10 +1507,15 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
int uid = rulesToRemove.keyAt(index);
updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT);
}
+ // Copy the keys for the firewall rules chain, which is guaranteed not to include
+ // default rules. We must not include default rules in the UIDs we send to
+ // ConnectivityManager#replaceFirewallChain, as this would have the opposite effect
+ // intended, leading such UIDs to be blocked or allowed erroneously.
+ applicableUidsForChain = uidFirewallRules.copyKeys();
}
final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
try {
- cm.replaceFirewallChain(chain, uids);
+ cm.replaceFirewallChain(chain, applicableUidsForChain);
} catch (RuntimeException e) {
Slog.w(TAG, "Error flushing firewall chain " + chain, e);
}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 78cffa6f4f79..1d9fed767991 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -416,6 +416,8 @@ public class LockSettingsService extends ILockSettings.Stub {
static class Injector {
protected Context mContext;
+ private ServiceThread mHandlerThread;
+ private Handler mHandler;
public Injector(Context context) {
mContext = context;
@@ -426,14 +428,20 @@ public class LockSettingsService extends ILockSettings.Stub {
}
public ServiceThread getServiceThread() {
- ServiceThread handlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND,
- true /*allowIo*/);
- handlerThread.start();
- return handlerThread;
+ if (mHandlerThread == null) {
+ mHandlerThread = new ServiceThread(TAG,
+ Process.THREAD_PRIORITY_BACKGROUND,
+ true /*allowIo*/);
+ mHandlerThread.start();
+ }
+ return mHandlerThread;
}
public Handler getHandler(ServiceThread handlerThread) {
- return new Handler(handlerThread.getLooper());
+ if (mHandler == null) {
+ mHandler = new Handler(handlerThread.getLooper());
+ }
+ return mHandler;
}
public LockSettingsStorage getStorage() {
@@ -514,7 +522,8 @@ public class LockSettingsService extends ILockSettings.Stub {
public RebootEscrowManager getRebootEscrowManager(RebootEscrowManager.Callbacks callbacks,
LockSettingsStorage storage) {
- return new RebootEscrowManager(mContext, callbacks, storage);
+ return new RebootEscrowManager(mContext, callbacks, storage,
+ getHandler(getServiceThread()));
}
public boolean hasEnrolledBiometrics(int userId) {
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
index 9b42cfca2e68..e1cd2c585146 100644
--- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
@@ -205,6 +205,8 @@ class RebootEscrowManager {
private final RebootEscrowKeyStoreManager mKeyStoreManager;
+ private final Handler mHandler;
+
PowerManager.WakeLock mWakeLock;
private ConnectivityManager.NetworkCallback mNetworkCallback;
@@ -399,19 +401,21 @@ class RebootEscrowManager {
}
}
- RebootEscrowManager(Context context, Callbacks callbacks, LockSettingsStorage storage) {
- this(new Injector(context, storage), callbacks, storage);
+ RebootEscrowManager(Context context, Callbacks callbacks, LockSettingsStorage storage,
+ Handler handler) {
+ this(new Injector(context, storage), callbacks, storage, handler);
}
@VisibleForTesting
RebootEscrowManager(Injector injector, Callbacks callbacks,
- LockSettingsStorage storage) {
+ LockSettingsStorage storage, Handler handler) {
mInjector = injector;
mCallbacks = callbacks;
mStorage = storage;
mUserManager = injector.getUserManager();
mEventLog = injector.getEventLog();
mKeyStoreManager = injector.getKeyStoreManager();
+ mHandler = handler;
}
/** Wrapper function to set error code serialized through handler, */
@@ -937,7 +941,7 @@ class RebootEscrowManager {
private void setRebootEscrowReady(boolean ready) {
if (mRebootEscrowReady != ready) {
- mRebootEscrowListener.onPreparedForReboot(ready);
+ mHandler.post(() -> mRebootEscrowListener.onPreparedForReboot(ready));
}
mRebootEscrowReady = ready;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index 2c0e909a5cc0..ea07fe77e588 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -42,6 +42,7 @@ import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.Pair;
import android.view.Display;
+import android.view.IWindow;
import android.view.IWindowManager;
import android.view.ViewDebug;
@@ -553,6 +554,22 @@ public class WindowManagerShellCommand extends ShellCommand {
return 0;
}
+ private void dumpLocalWindowAsync(IWindow client, ParcelFileDescriptor pfd) {
+ // Make it asynchronous to avoid writer from being blocked
+ // by waiting for the buffer to be consumed in the same process.
+ IoThread.getExecutor().execute(() -> {
+ synchronized (mInternal.mGlobalLock) {
+ try {
+ client.executeCommand(ViewDebug.REMOTE_COMMAND_DUMP_ENCODED, null, pfd);
+ } catch (Exception e) {
+ // Ignore RemoteException for local call. Just print trace for other
+ // exceptions caused by RC with tolerable low possibility.
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+
private int runDumpVisibleWindowViews(PrintWriter pw) {
if (!mInternal.checkCallingPermission(android.Manifest.permission.DUMP,
"runDumpVisibleWindowViews()")) {
@@ -575,16 +592,7 @@ public class WindowManagerShellCommand extends ShellCommand {
pipe = new ByteTransferPipe();
final ParcelFileDescriptor pfd = pipe.getWriteFd();
if (w.isClientLocal()) {
- // Make it asynchronous to avoid writer from being blocked
- // by waiting for the buffer to be consumed in the same process.
- IoThread.getExecutor().execute(() -> {
- try {
- w.mClient.executeCommand(
- ViewDebug.REMOTE_COMMAND_DUMP_ENCODED, null, pfd);
- } catch (RemoteException e) {
- // Ignore for local call.
- }
- });
+ dumpLocalWindowAsync(w.mClient, pfd);
} else {
w.mClient.executeCommand(
ViewDebug.REMOTE_COMMAND_DUMP_ENCODED, null, pfd);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java
index ce6bd6ccbe51..bb12d699a15c 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java
@@ -74,6 +74,8 @@ import org.mockito.ArgumentCaptor;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import javax.crypto.SecretKey;
@@ -327,16 +329,30 @@ public class RebootEscrowManagerTests {
mInjected = mock(MockableRebootEscrowInjected.class);
mMockInjector = new MockInjector(mContext, mUserManager, mRebootEscrow,
mKeyStoreManager, mStorage, mInjected);
- mService = new RebootEscrowManager(mMockInjector, mCallbacks, mStorage);
HandlerThread thread = new HandlerThread("RebootEscrowManagerTest");
thread.start();
mHandler = new Handler(thread.getLooper());
+ mService = new RebootEscrowManager(mMockInjector, mCallbacks, mStorage, mHandler);
+
}
private void setServerBasedRebootEscrowProvider() throws Exception {
mMockInjector = new MockInjector(mContext, mUserManager, mServiceConnection,
mKeyStoreManager, mStorage, mInjected);
- mService = new RebootEscrowManager(mMockInjector, mCallbacks, mStorage);
+ mService = new RebootEscrowManager(mMockInjector, mCallbacks, mStorage, mHandler);
+ }
+
+ private void waitForHandler() throws InterruptedException {
+ // Wait for handler to complete processing.
+ CountDownLatch latch = new CountDownLatch(1);
+ mHandler.post(latch::countDown);
+ assertTrue(latch.await(5, TimeUnit.SECONDS));
+
+ }
+
+ private void callToRebootEscrowIfNeededAndWait(int userId) throws InterruptedException {
+ mService.callToRebootEscrowIfNeeded(userId, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ waitForHandler();
}
@Test
@@ -346,7 +362,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mRebootEscrow);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mRebootEscrow, never()).storeKey(any());
}
@@ -358,8 +374,7 @@ public class RebootEscrowManagerTests {
mService.setRebootEscrowListener(mockListener);
mService.prepareRebootEscrow();
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
- verify(mockListener).onPreparedForReboot(eq(true));
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
assertFalse(mStorage.hasRebootEscrowServerBlob());
}
@@ -369,7 +384,7 @@ public class RebootEscrowManagerTests {
RebootEscrowListener mockListener = mock(RebootEscrowListener.class);
mService.setRebootEscrowListener(mockListener);
mService.prepareRebootEscrow();
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
clearInvocations(mRebootEscrow);
@@ -393,7 +408,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mRebootEscrow);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mRebootEscrow, never()).storeKey(any());
@@ -417,7 +432,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mServiceConnection);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
@@ -438,7 +453,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mRebootEscrow);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mRebootEscrow, never()).storeKey(any());
@@ -456,10 +471,9 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mRebootEscrow);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
- mService.callToRebootEscrowIfNeeded(SECURE_SECONDARY_USER_ID, FAKE_SP_VERSION,
- FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(SECURE_SECONDARY_USER_ID);
verify(mRebootEscrow, never()).storeKey(any());
assertTrue(mStorage.hasRebootEscrow(PRIMARY_USER_ID));
@@ -491,7 +505,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mRebootEscrow);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mRebootEscrow, never()).storeKey(any());
@@ -514,7 +528,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mRebootEscrow);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mRebootEscrow, never()).storeKey(any());
@@ -557,7 +571,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mServiceConnection);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
@@ -601,7 +615,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mServiceConnection);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
@@ -646,7 +660,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mServiceConnection);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
@@ -692,7 +706,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mServiceConnection);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
@@ -741,7 +755,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mServiceConnection);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
@@ -794,7 +808,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mServiceConnection);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
@@ -849,7 +863,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mServiceConnection);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
@@ -896,7 +910,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mServiceConnection);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
@@ -952,7 +966,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mServiceConnection);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
@@ -1011,7 +1025,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mServiceConnection);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
@@ -1071,7 +1085,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mServiceConnection);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
@@ -1127,7 +1141,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mServiceConnection);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mServiceConnection, never()).wrapBlob(any(), anyLong(), anyLong());
@@ -1179,7 +1193,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mRebootEscrow);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mRebootEscrow, never()).storeKey(any());
@@ -1210,7 +1224,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mRebootEscrow);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mRebootEscrow, never()).storeKey(any());
@@ -1238,7 +1252,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mRebootEscrow);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mRebootEscrow, never()).storeKey(any());
@@ -1277,7 +1291,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mRebootEscrow);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
verify(mRebootEscrow, never()).storeKey(any());
@@ -1312,7 +1326,7 @@ public class RebootEscrowManagerTests {
mService.prepareRebootEscrow();
clearInvocations(mRebootEscrow);
- mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN);
+ callToRebootEscrowIfNeededAndWait(PRIMARY_USER_ID);
verify(mockListener).onPreparedForReboot(eq(true));
assertTrue(mStorage.hasRebootEscrow(PRIMARY_USER_ID));
verify(mRebootEscrow, never()).storeKey(any());
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 49ad58550db8..7c60f81259c7 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -82,7 +82,7 @@ import java.util.concurrent.ConcurrentHashMap;
* must call {@link #destroy()} to signal to the framework that the {@code Connection} is no
* longer used and associated resources may be recovered.
* <p>
- * Subclasses of {@code Connection} override the {@code on*} methods to provide the the
+ * Subclasses of {@code Connection} override the {@code on*} methods to provide the
* {@link ConnectionService}'s implementation of calling functionality. The {@code on*} methods are
* called by Telecom to inform an instance of a {@code Connection} of actions specific to that
* {@code Connection} instance.
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 6fe9bf97c5c3..ac740166a024 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -1207,13 +1207,8 @@ public class ServiceState implements Parcelable {
/**
* Initialize the service state. Set everything to the default value.
- *
- * @param legacyMode {@code true} if the device is on IWLAN legacy mode, where IWLAN is
- * considered as a RAT on WWAN {@link NetworkRegistrationInfo}. {@code false} if the device
- * is on AP-assisted mode, where IWLAN should be reported through WLAN.
- * {@link NetworkRegistrationInfo}.
*/
- private void init(boolean legacyMode) {
+ private void init() {
if (DBG) Rlog.d(LOG_TAG, "init");
mVoiceRegState = STATE_OUT_OF_SERVICE;
mDataRegState = STATE_OUT_OF_SERVICE;
@@ -1245,13 +1240,11 @@ public class ServiceState implements Parcelable {
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
.build());
- if (!legacyMode) {
- addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
- .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
- .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
- .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
- .build());
- }
+ addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
+ .build());
}
mOperatorAlphaLongRaw = null;
mOperatorAlphaShortRaw = null;
@@ -1260,11 +1253,11 @@ public class ServiceState implements Parcelable {
}
public void setStateOutOfService() {
- init(true);
+ init();
}
public void setStateOff() {
- init(true);
+ init();
mVoiceRegState = STATE_POWER_OFF;
mDataRegState = STATE_POWER_OFF;
}
@@ -1272,14 +1265,11 @@ public class ServiceState implements Parcelable {
/**
* Set the service state to out-of-service
*
- * @param legacyMode {@code true} if the device is on IWLAN legacy mode, where IWLAN is
- * considered as a RAT on WWAN {@link NetworkRegistrationInfo}. {@code false} if the device
- * is on AP-assisted mode, where IWLAN should be reported through WLAN.
* @param powerOff {@code true} if this is a power off case (i.e. Airplane mode on).
* @hide
*/
- public void setOutOfService(boolean legacyMode, boolean powerOff) {
- init(legacyMode);
+ public void setOutOfService(boolean powerOff) {
+ init();
if (powerOff) {
mVoiceRegState = STATE_POWER_OFF;
mDataRegState = STATE_POWER_OFF;
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 59b822ebecbf..46cf979fa8e3 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2586,18 +2586,41 @@ public class SubscriptionManager {
}
/**
- * Set a field in the subscription database. Note not all fields are supported.
+ * Returns a constant indicating the state of sim for the slot index.
*
- * @param subscriptionId Subscription Id of Subscription.
- * @param columnName Column name in the database. Note not all fields are supported.
- * @param value Value to store in the database.
+ * @param slotIndex
*
- * @throws IllegalArgumentException if {@code subscriptionId} is invalid, or the field is not
- * exposed.
- * @throws SecurityException if callers do not hold the required permission.
- *
- * @see android.provider.Telephony.SimInfo for all the columns.
+ * {@See TelephonyManager#SIM_STATE_UNKNOWN}
+ * {@See TelephonyManager#SIM_STATE_ABSENT}
+ * {@See TelephonyManager#SIM_STATE_PIN_REQUIRED}
+ * {@See TelephonyManager#SIM_STATE_PUK_REQUIRED}
+ * {@See TelephonyManager#SIM_STATE_NETWORK_LOCKED}
+ * {@See TelephonyManager#SIM_STATE_READY}
+ * {@See TelephonyManager#SIM_STATE_NOT_READY}
+ * {@See TelephonyManager#SIM_STATE_PERM_DISABLED}
+ * {@See TelephonyManager#SIM_STATE_CARD_IO_ERROR}
*
+ * {@hide}
+ */
+ public static int getSimStateForSlotIndex(int slotIndex) {
+ int simState = TelephonyManager.SIM_STATE_UNKNOWN;
+
+ try {
+ ISub iSub = TelephonyManager.getSubscriptionService();
+ if (iSub != null) {
+ simState = iSub.getSimStateForSlotIndex(slotIndex);
+ }
+ } catch (RemoteException ex) {
+ }
+
+ return simState;
+ }
+
+ /**
+ * Store properties associated with SubscriptionInfo in database
+ * @param subId Subscription Id of Subscription
+ * @param propKey Column name in database associated with SubscriptionInfo
+ * @param propValue Value to store in DB for particular subId & column name
* @hide
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 9d418e144f4c..7a19d36ba743 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3504,7 +3504,7 @@ public class TelephonyManager {
"state as absent");
return SIM_STATE_ABSENT;
}
- return getSimStateForSlotIndex(slotIndex);
+ return SubscriptionManager.getSimStateForSlotIndex(slotIndex);
}
/**
@@ -3651,7 +3651,9 @@ public class TelephonyManager {
@Deprecated
public @SimState int getSimApplicationState(int physicalSlotIndex) {
int activePort = getFirstActivePortIndex(physicalSlotIndex);
- int simState = getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex, activePort));
+ int simState =
+ SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex,
+ activePort));
return getSimApplicationStateFromSimState(simState);
}
@@ -3677,7 +3679,9 @@ public class TelephonyManager {
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @SimState int getSimApplicationState(int physicalSlotIndex, int portIndex) {
- int simState = getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex, portIndex));
+ int simState =
+ SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex,
+ portIndex));
return getSimApplicationStateFromSimState(simState);
}
@@ -3746,7 +3750,7 @@ public class TelephonyManager {
*/
@RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
public @SimState int getSimState(int slotIndex) {
- int simState = getSimStateForSlotIndex(slotIndex);
+ int simState = SubscriptionManager.getSimStateForSlotIndex(slotIndex);
if (simState == SIM_STATE_LOADED) {
simState = SIM_STATE_READY;
}
@@ -17002,30 +17006,4 @@ public class TelephonyManager {
}
return false;
}
-
- /**
- * Returns a constant indicating the state of sim for the slot index.
- *
- * @param slotIndex Logical SIM slot index.
- *
- * @see TelephonyManager.SimState
- *
- * @hide
- */
- @SimState
- public static int getSimStateForSlotIndex(int slotIndex) {
- try {
- ITelephony telephony = ITelephony.Stub.asInterface(
- TelephonyFrameworkInitializer
- .getTelephonyServiceManager()
- .getTelephonyServiceRegisterer()
- .get());
- if (telephony != null) {
- return telephony.getSimStateForSlotIndex(slotIndex);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Error in getSimStateForSlotIndex: " + e);
- }
- return TelephonyManager.SIM_STATE_UNKNOWN;
- }
}
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index c5f6902062ff..2cf5e67ad287 100644
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -272,6 +272,11 @@ interface ISub {
boolean isSubscriptionEnabled(int subId);
int getEnabledSubscriptionId(int slotIndex);
+ /**
+ * Get the SIM state for the slot index
+ * @return SIM state as the ordinal of IccCardConstants.State
+ */
+ int getSimStateForSlotIndex(int slotIndex);
boolean isActiveSubId(int subId, String callingPackage, String callingFeatureId);
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index ecafe702ea4e..da1ffcdea812 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2564,11 +2564,4 @@ interface ITelephony {
* @hide
*/
boolean isRemovableEsimDefaultEuicc(String callingPackage);
-
- /**
- * Get the SIM state for the logical SIM slot index.
- *
- * @param slotIndex Logical SIM slot index.
- */
- int getSimStateForSlotIndex(int slotIndex);
}
diff --git a/tests/EnforcePermission/Android.bp b/tests/EnforcePermission/Android.bp
new file mode 100644
index 000000000000..719a89817a9d
--- /dev/null
+++ b/tests/EnforcePermission/Android.bp
@@ -0,0 +1,22 @@
+// Copyright (C) 2023 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 {
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+filegroup {
+ name: "frameworks-enforce-permission-test-aidl",
+ srcs: ["aidl/**/*.aidl"],
+}
diff --git a/tests/EnforcePermission/aidl/android/tests/enforcepermission/INested.aidl b/tests/EnforcePermission/aidl/android/tests/enforcepermission/INested.aidl
new file mode 100644
index 000000000000..1eb773dc19b8
--- /dev/null
+++ b/tests/EnforcePermission/aidl/android/tests/enforcepermission/INested.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2023 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.tests.enforcepermission;
+
+interface INested {
+ @EnforcePermission("ACCESS_NETWORK_STATE")
+ void ProtectedByAccessNetworkState();
+
+ @EnforcePermission("READ_SYNC_SETTINGS")
+ void ProtectedByReadSyncSettings();
+}
diff --git a/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl b/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl
new file mode 100644
index 000000000000..18e3aecfa832
--- /dev/null
+++ b/tests/EnforcePermission/aidl/android/tests/enforcepermission/IProtected.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 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.tests.enforcepermission;
+
+interface IProtected {
+ @EnforcePermission("INTERNET")
+ void ProtectedByInternet();
+
+ @EnforcePermission("VIBRATE")
+ void ProtectedByVibrate();
+
+ @EnforcePermission("INTERNET")
+ void ProtectedByInternetAndVibrateImplicitly();
+
+ @EnforcePermission("INTERNET")
+ void ProtectedByInternetAndAccessNetworkStateImplicitly();
+
+ @EnforcePermission("INTERNET")
+ void ProtectedByInternetAndReadSyncSettingsImplicitly();
+}
diff --git a/tests/EnforcePermission/service-app/Android.bp b/tests/EnforcePermission/service-app/Android.bp
new file mode 100644
index 000000000000..a4ac1d7c6134
--- /dev/null
+++ b/tests/EnforcePermission/service-app/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2023 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+ name: "EnforcePermissionTestHelper",
+ srcs: [
+ "src/**/*.java",
+ ":frameworks-enforce-permission-test-aidl",
+ ],
+ platform_apis: true,
+ certificate: "platform",
+}
diff --git a/tests/EnforcePermission/service-app/AndroidManifest.xml b/tests/EnforcePermission/service-app/AndroidManifest.xml
new file mode 100644
index 000000000000..ddafe15ab88f
--- /dev/null
+++ b/tests/EnforcePermission/service-app/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.tests.enforcepermission.service">
+ <application>
+ <service
+ android:name=".TestService"
+ android:exported="true" />
+
+ <service
+ android:name=".NestedTestService"
+ android:exported="true" />
+ </application>
+</manifest>
diff --git a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java
new file mode 100644
index 000000000000..7879a1214c01
--- /dev/null
+++ b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/NestedTestService.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright (C) 2023 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.tests.enforcepermission.service;
+
+import android.annotation.EnforcePermission;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.tests.enforcepermission.INested;
+import android.util.Log;
+
+public class NestedTestService extends Service {
+ private static final String TAG = "EnforcePermission.NestedTestService";
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ Log.i(TAG, "onBind");
+ return mBinder;
+ }
+
+ private final INested.Stub mBinder = new INested.Stub() {
+ @Override
+ @EnforcePermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+ public void ProtectedByAccessNetworkState() {
+ ProtectedByAccessNetworkState_enforcePermission();
+ }
+
+ @Override
+ @EnforcePermission(android.Manifest.permission.READ_SYNC_SETTINGS)
+ public void ProtectedByReadSyncSettings() {
+ ProtectedByReadSyncSettings_enforcePermission();
+ }
+ };
+}
diff --git a/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java
new file mode 100644
index 000000000000..e9b897db1294
--- /dev/null
+++ b/tests/EnforcePermission/service-app/src/android/tests/enforcepermission/service/TestService.java
@@ -0,0 +1,119 @@
+/**
+ * Copyright (C) 2023 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.tests.enforcepermission.service;
+
+import android.annotation.EnforcePermission;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.tests.enforcepermission.INested;
+import android.tests.enforcepermission.IProtected;
+import android.util.Log;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class TestService extends Service {
+
+ private static final String TAG = "EnforcePermission.TestService";
+ private volatile ServiceConnection mNestedServiceConnection;
+
+ @Override
+ public void onCreate() {
+ mNestedServiceConnection = new ServiceConnection();
+ Intent intent = new Intent(this, NestedTestService.class);
+ boolean bound = bindService(intent, mNestedServiceConnection, Context.BIND_AUTO_CREATE);
+ if (!bound) {
+ Log.wtf(TAG, "bindService() on NestedTestService failed");
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ unbindService(mNestedServiceConnection);
+ }
+
+ private static final class ServiceConnection implements android.content.ServiceConnection {
+ private volatile CompletableFuture<INested> mFuture = new CompletableFuture<>();
+
+ public INested get() {
+ try {
+ return mFuture.get(1, TimeUnit.SECONDS);
+ } catch (ExecutionException | InterruptedException | TimeoutException e) {
+ throw new RuntimeException("Unable to reach NestedTestService: " + e.getMessage());
+ }
+ }
+
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ mFuture.complete(INested.Stub.asInterface(service));
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ mFuture = new CompletableFuture<>();
+ }
+ };
+
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+ private final IProtected.Stub mBinder = new IProtected.Stub() {
+ @Override
+ @EnforcePermission(android.Manifest.permission.INTERNET)
+ public void ProtectedByInternet() {
+ ProtectedByInternet_enforcePermission();
+ }
+
+ @Override
+ @EnforcePermission(android.Manifest.permission.VIBRATE)
+ public void ProtectedByVibrate() {
+ ProtectedByVibrate_enforcePermission();
+ }
+
+ @Override
+ @EnforcePermission(android.Manifest.permission.INTERNET)
+ public void ProtectedByInternetAndVibrateImplicitly() {
+ ProtectedByInternetAndVibrateImplicitly_enforcePermission();
+
+ ProtectedByVibrate();
+ }
+
+ @Override
+ @EnforcePermission(android.Manifest.permission.INTERNET)
+ public void ProtectedByInternetAndAccessNetworkStateImplicitly() throws RemoteException {
+ ProtectedByInternetAndAccessNetworkStateImplicitly_enforcePermission();
+
+ mNestedServiceConnection.get().ProtectedByAccessNetworkState();
+
+ }
+
+ @Override
+ @EnforcePermission(android.Manifest.permission.INTERNET)
+ public void ProtectedByInternetAndReadSyncSettingsImplicitly() throws RemoteException {
+ ProtectedByInternetAndReadSyncSettingsImplicitly_enforcePermission();
+
+ mNestedServiceConnection.get().ProtectedByReadSyncSettings();
+ }
+ };
+}
diff --git a/tests/EnforcePermission/test-app/Android.bp b/tests/EnforcePermission/test-app/Android.bp
new file mode 100644
index 000000000000..305ed8f0dadc
--- /dev/null
+++ b/tests/EnforcePermission/test-app/Android.bp
@@ -0,0 +1,38 @@
+// Copyright (C) 2023 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 {
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+ name: "EnforcePermissionTests",
+ srcs: [
+ "src/**/*.java",
+ ":frameworks-enforce-permission-test-aidl",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ ],
+ libs: [
+ "android.test.base",
+ "android.test.runner",
+ ],
+ data: [
+ ":EnforcePermissionTestHelper",
+ ],
+ platform_apis: true,
+ certificate: "platform",
+ test_suites: ["general-tests"],
+}
diff --git a/tests/EnforcePermission/test-app/AndroidManifest.xml b/tests/EnforcePermission/test-app/AndroidManifest.xml
new file mode 100644
index 000000000000..4a0c6a86628f
--- /dev/null
+++ b/tests/EnforcePermission/test-app/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.tests.enforcepermission.tests">
+
+ <!-- Expected for the tests (not actually used) -->
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
+
+ <queries>
+ <package android:name="android.tests.enforcepermission.service" />
+ </queries>
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.tests.enforcepermission.tests"/>
+</manifest>
diff --git a/tests/EnforcePermission/test-app/AndroidTest.xml b/tests/EnforcePermission/test-app/AndroidTest.xml
new file mode 100644
index 000000000000..120381a7fb83
--- /dev/null
+++ b/tests/EnforcePermission/test-app/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+<configuration description="Runs EnforcePermission End-to-End Tests">
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="EnforcePermissionTestHelper.apk"/>
+ <option name="test-file-name" value="EnforcePermissionTests.apk"/>
+ <option name="cleanup-apks" value="true" />
+ </target_preparer>
+
+ <option name="test-tag" value="EnforcePermissionTests"/>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="android.tests.enforcepermission.tests"/>
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
+ </test>
+</configuration>
diff --git a/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java b/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java
new file mode 100644
index 000000000000..d2a4a037f125
--- /dev/null
+++ b/tests/EnforcePermission/test-app/src/android/tests/enforcepermission/tests/ServiceTest.java
@@ -0,0 +1,129 @@
+/**
+ * Copyright (C) 2023 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.tests.enforcepermission.tests;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.tests.enforcepermission.IProtected;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+@RunWith(AndroidJUnit4.class)
+public class ServiceTest {
+
+ private static final String TAG = "EnforcePermission.Tests";
+ private static final String SERVICE_NAME = "android.tests.enforcepermission.service";
+ private static final int SERVICE_TIMEOUT_SEC = 5;
+
+ private Context mContext;
+ private volatile ServiceConnection mServiceConnection;
+
+ @Before
+ public void bindTestService() throws Exception {
+ Log.d(TAG, "bindTestService");
+ mContext = InstrumentationRegistry.getTargetContext();
+ mServiceConnection = new ServiceConnection();
+ Intent intent = new Intent();
+ intent.setClassName(SERVICE_NAME, SERVICE_NAME + ".TestService");
+ assertTrue(mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE));
+ }
+
+ @After
+ public void unbindTestService() throws Exception {
+ mContext.unbindService(mServiceConnection);
+ }
+
+ private static final class ServiceConnection implements android.content.ServiceConnection {
+ private volatile CompletableFuture<IProtected> mFuture = new CompletableFuture<>();
+
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ mFuture.complete(IProtected.Stub.asInterface(service));
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName className) {
+ mFuture = new CompletableFuture<>();
+ }
+
+ public IProtected get() {
+ try {
+ return mFuture.get(SERVICE_TIMEOUT_SEC, TimeUnit.SECONDS);
+ } catch (ExecutionException | InterruptedException | TimeoutException e) {
+ throw new RuntimeException("Unable to reach TestService: " + e.toString());
+ }
+ }
+ }
+
+ @Test
+ public void testImmediatePermissionGranted_succeeds()
+ throws RemoteException {
+ mServiceConnection.get().ProtectedByInternet();
+ }
+
+ @Test
+ public void testImmediatePermissionNotGranted_fails()
+ throws RemoteException {
+ final Exception ex = assertThrows(SecurityException.class,
+ () -> mServiceConnection.get().ProtectedByVibrate());
+ assertThat(ex.getMessage(), containsString("VIBRATE"));
+ }
+
+ @Test
+ public void testImmediatePermissionGrantedButImplicitLocalNotGranted_fails()
+ throws RemoteException {
+ final Exception ex = assertThrows(SecurityException.class,
+ () -> mServiceConnection.get().ProtectedByInternetAndVibrateImplicitly());
+ assertThat(ex.getMessage(), containsString("VIBRATE"));
+ }
+
+ @Test
+ public void testImmediatePermissionGrantedButImplicitNestedNotGranted_fails()
+ throws RemoteException {
+ final Exception ex = assertThrows(SecurityException.class,
+ () -> mServiceConnection.get()
+ .ProtectedByInternetAndAccessNetworkStateImplicitly());
+ assertThat(ex.getMessage(), containsString("ACCESS_NETWORK_STATE"));
+ }
+
+ @Test
+ public void testImmediatePermissionGrantedAndImplicitNestedGranted_succeeds()
+ throws RemoteException {
+ mServiceConnection.get().ProtectedByInternetAndReadSyncSettingsImplicitly();
+ }
+}