in niap-cc/Permissions/Tester/app/src/main/java/com/android/certifications/niap/permissions/InstallPermissionTester.java [139:534]
public InstallPermissionTester(TestConfiguration configuration, Activity activity) {
super(configuration, activity);
mConnectivityManager = (ConnectivityManager) mContext.getSystemService(
Context.CONNECTIVITY_SERVICE);
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
mBluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = mBluetoothManager.getAdapter();
mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
mPackageInstaller = mPackageManager.getPackageInstaller();
mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
Context.DEVICE_POLICY_SERVICE);
mWallpaperManager = (WallpaperManager) mContext.getSystemService(Context.WALLPAPER_SERVICE);
mConsumerIrManager = (ConsumerIrManager) mContext.getSystemService(
Context.CONSUMER_IR_SERVICE);
mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mPermissionTasks = new HashMap<>();
mPermissionTasks.put(ACCESS_NETWORK_STATE,
new PermissionTest(false, () -> mConnectivityManager.getActiveNetwork()));
mPermissionTasks.put(ACCESS_WIFI_STATE,
new PermissionTest(false, () -> mWifiManager.getConfiguredNetworks()));
// android.permission.AUTHENTICATE_ACCOUNTS has been removed.
mPermissionTasks.put(BLUETOOTH, new PermissionTest(false, () -> {
if (mBluetoothAdapter == null) {
throw new BypassTestException(
"A bluetooth adapter is not available to run this test");
}
mBluetoothAdapter.getAddress();
}));
mPermissionTasks.put(BLUETOOTH_ADMIN, new PermissionTest(false, () -> {
if (mBluetoothAdapter == null) {
throw new BypassTestException(
"A bluetooth adapter is not available to run this test");
}
if (mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.disable();
mBluetoothAdapter.enable();
} else {
mBluetoothAdapter.enable();
}
}));
mPermissionTasks.put(BROADCAST_STICKY, new PermissionTest(false, () -> {
Intent intent = new Intent();
mContext.sendStickyBroadcast(intent);
}));
// android.permission.CALL_COMPANION_APP requires an active call.
mPermissionTasks.put(CHANGE_NETWORK_STATE, new PermissionTest(false, () -> {
NetworkRequest networkRequest = new NetworkRequest.Builder().addCapability(
NetworkCapabilities.NET_CAPABILITY_INTERNET).build();
mConnectivityManager.requestNetwork(networkRequest, new NetworkCallback() {
@Override
public void onAvailable(Network network) {
}
});
}));
mPermissionTasks.put(CHANGE_WIFI_MULTICAST_STATE, new PermissionTest(false, () -> {
WifiManager.MulticastLock multicastLock = mWifiManager.createMulticastLock(TAG);
multicastLock.acquire();
multicastLock.release();
}));
mPermissionTasks
.put(CHANGE_WIFI_STATE,
new PermissionTest(false, () -> mWifiManager.setWifiEnabled(true)));
mPermissionTasks.put(DISABLE_KEYGUARD, new PermissionTest(false, () -> {
KeyguardManager.KeyguardLock keyguardLock = mKeyguardManager.newKeyguardLock(TAG);
keyguardLock.disableKeyguard();
}));
mPermissionTasks.put(EXPAND_STATUS_BAR, new PermissionTest(false, () -> {
Object statusBarManager = mContext.getSystemService("statusbar");
invokeReflectionCall(statusBarManager.getClass(), "expandNotificationsPanel",
statusBarManager, null);
// A short sleep is required to allow the notification panel to be expanded before
// collapsing it to clean up after this test.
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
mLogger.logDebug("Caught an InterruptedException: ", e);
}
invokeReflectionCall(statusBarManager.getClass(), "collapsePanels",
statusBarManager, null);
}));
// andorid.permission.FLASHLIGHT has been removed.
mPermissionTasks.put(FOREGROUND_SERVICE, new PermissionTest(true, () -> {
// This test must run as a custom test because it requires a separate service be run in
// in the foreground that can invoke startForeground.
String permission = FOREGROUND_SERVICE;
boolean permissionGranted = isPermissionGranted(permission);
try {
Intent serviceIntent = new Intent(mContext, TestService.class);
serviceIntent.putExtra(EXTRA_PERMISSION_NAME, permission);
serviceIntent.putExtra(EXTRA_PERMISSION_GRANTED, permissionGranted);
mContext.startForegroundService(serviceIntent);
} catch (Throwable t) {
StatusLogger.logTestError(permission, t);
}
}));
// android.permission.GET_PACKAGE_SIZE only guards PackageManager#getPackageSizeInfoAsUser
// which is hidden and results in an UnsupportedOperationException after O.
// android.permission.GET_TASKS has been deprecated and is no longer enforced.
// android.permission.INSTALL_SHORTCUT is no longer used.
mPermissionTasks.put(INTERNET, new PermissionTest(false, () -> {
try {
// Use a simple ServerSocket with a value of 0 to pick a free port to verify the
// Internet permission.
ServerSocket socket = new ServerSocket(0);
socket.close();
} catch (Throwable t) {
// Sockets that require the Internet permission will not throw SecurityExceptions
// but instead will throw SocketExceptions with a message containing EACCES
// (Permission Denied).
// NOTE: Later versions of the platform also return an EPERM error for this case.
if (t instanceof SocketException && (t.getMessage().contains("EACCES")
|| t.getMessage().contains("EPERM"))) {
throw new SecurityException(t);
} else {
throw new UnexpectedPermissionTestFailureException(t);
}
}
}));
mPermissionTasks.put(KILL_BACKGROUND_PROCESSES, new PermissionTest(false,
() -> mActivityManager.killBackgroundProcesses(Constants.COMPANION_PACKAGE)));
// android.permission.MANAGE_ACCOUNTS has been removed.
mPermissionTasks.put(MODIFY_AUDIO_SETTINGS, new PermissionTest(false, () -> {
// This API does not throw a SecurityException but instead just logs a permission denial
// similar to the following in logcat:
// AS.AudioService: Audio Settings Permission Denial: setMicrophoneMute() from
// pid=26925, uid=10250
boolean micMuted = mAudioManager.isMicrophoneMute();
mAudioManager.setMicrophoneMute(!micMuted);
if (mAudioManager.isMicrophoneMute() == micMuted) {
throw new SecurityException("mic mute status could not be changed");
}
// restore the mic mute status to the original setting
mAudioManager.setMicrophoneMute(micMuted);
}));
mPermissionTasks.put(MANAGE_OWN_CALLS, new PermissionTest(false, () -> {
TelecomManager telecomManager = (TelecomManager) mContext.getSystemService(
Context.TELECOM_SERVICE);
Uri numberUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, "886", null);
telecomManager.addNewIncomingCall(null, null);
PhoneAccountHandle phoneAccountHandle = new PhoneAccountHandle(
new ComponentName(mContext, MainActivity.class), "TestId");
telecomManager.isIncomingCallPermitted(phoneAccountHandle);
}));
mPermissionTasks.put(NFC, new PermissionTest(false, () -> {
// SELinux blocks access to the NFC service from platform apps, so skip this test if the
// app is platform signed.
// SELinux : avc: denied { find } for service=nfc pid=24835 uid=10144
// scontext=u:r:platform_app:s0:c512,c768 tcontext=u:object_r:nfc_service:s0
// tclass=service_manager permissive=0
// NFC : could not retrieve NFC service
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
if (adapter == null) {
throw new BypassTestException("An NFC adapter is not available to run this test");
}
adapter.setNdefPushMessage(null, mActivity);
CardEmulation emulation = CardEmulation.getInstance(adapter);
emulation.isDefaultServiceForCategory(new ComponentName(mContext, TestService.class),
CardEmulation.CATEGORY_PAYMENT);
}));
// android.permission.NFC_TRANSACTION_EVENT only guards broadcasts during NFC transactions.
// android.permission.PERSISTENT_ACTIVITY is no longer used.
// android.permission.READ_HISTORY_BOOKMARKS has been removed.
// android.permission.READ_INSTALL_SESSIONS is no longer used.
// android.permission.READ_PROFILE has been removed.
// android.permission.READ_SOCIAL_STREAM has been removed.
mPermissionTasks.put(READ_SYNC_SETTINGS,
new PermissionTest(false, () -> ContentResolver.getMasterSyncAutomatically()));
mPermissionTasks
.put(READ_SYNC_STATS,
new PermissionTest(false, () -> ContentResolver.getCurrentSyncs()));
// android.permission.READ_USER_DICTIONARY has been removed.
// android.permission.RECEIVE_BOOT_COMPLETED only guards receiving the boot
// completed broadcast.
mPermissionTasks.put(REORDER_TASKS,
new PermissionTest(false, () -> mActivityManager.moveTaskToFront(2, 0)));
// android.permission.REQUEST_COMKPANION_RUN_IN_BACKGROUND requires companion device
// with which to associate this app.
// android.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND requires companion device
// with which to associate this app.
mPermissionTasks.put(REQUEST_DELETE_PACKAGES, new PermissionTest(false, () -> {
Intent intent = new Intent(mActivity, TestActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
// Use a version of this package that does not exist on the device to make this a
// noop after the permission check.
VersionedPackage versionedPackage = new VersionedPackage(mPackageName, 0);
mPackageInstaller.uninstall(versionedPackage, pendingIntent.getIntentSender());
}));
// android.permission.RESTART_PACKAGES only guarded ActivityManager#restartPackages which
// is no longer supported.
mPermissionTasks
.put(SET_WALLPAPER,
new PermissionTest(false, () -> mWallpaperManager.clearWallpaper()));
mPermissionTasks.put(SET_WALLPAPER_HINTS, new PermissionTest(false, () -> {
Rect rect = new Rect(0, 0, 1, 1);
mWallpaperManager.setDisplayPadding(rect);
}));
// android.permission.SUBSCRIBED_FEEDS_READ has been removed.
// android.permission.SUBSCRIBED_FEEDS_WRITE has been removed.
mPermissionTasks.put(TRANSMIT_IR, new PermissionTest(false, () -> {
try {
mConsumerIrManager.getCarrierFrequencies();
} catch (UnsupportedOperationException e) {
// This Exception indicates the app has been granted the required permission to
// invoke this API but the device does not have the IR feature.
}
}));
// android.permission.UNINSTALL_SHORTCUT is no longer used.
mPermissionTasks.put(USE_BIOMETRIC, new PermissionTest(false, () -> {
if (mDeviceApiLevel == Build.VERSION_CODES.P) {
FingerprintManager fingerprintManager =
(FingerprintManager) mContext.getSystemService(
Context.FINGERPRINT_SERVICE);
if (fingerprintManager == null) {
throw new BypassTestException(
"The FingerprintManager is not available on this device");
}
fingerprintManager.isHardwareDetected();
} else {
// The BiometricManager was introduced in Android 10 and is more appropriate to use
// for this permission. Android 10 introduced the canAuthenticate method while
// Android 11 deprecated that in favor of an overloaded version that accepts
// an int representing Authenticators.
BiometricManager biometricManager = (BiometricManager) mContext.getSystemService(
Context.BIOMETRIC_SERVICE);
if (mDeviceApiLevel == Build.VERSION_CODES.Q) {
biometricManager.canAuthenticate();
} else {
biometricManager.canAuthenticate(
BiometricManager.Authenticators.BIOMETRIC_STRONG);
}
}
}));
// android.permission.USE_CREDENTIALS has been removed.
mPermissionTasks.put(USE_FINGERPRINT,
new PermissionTest(false, () -> {
FingerprintManager fingerprintManager =
(FingerprintManager) mContext.getSystemService(
Context.FINGERPRINT_SERVICE);
if (fingerprintManager == null) {
throw new BypassTestException(
"The FingerprintManager is not available on this device");
}
fingerprintManager.hasEnrolledFingerprints();
}));
mPermissionTasks.put(VIBRATE, new PermissionTest(false, () -> mVibrator
.vibrate(VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE))));
mPermissionTasks.put(WAKE_LOCK, new PermissionTest(false, () -> {
PowerManager.WakeLock wakeLock = mPowerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
InstallPermissionTester.class.getSimpleName() + "::" + TAG);
wakeLock.acquire();
wakeLock.release();
}));
// android.permission.WRITE_HISTORY_BOOKMARKS has been removed.
// android.permission.WRITE_PROFILE has been removed.
// android.permission.WRITE_SMS has been removed.
// android.permission.WRITE_SOCIAL_STREAM has been removed.
mPermissionTasks.put(WRITE_SYNC_SETTINGS,
new PermissionTest(false, () -> ContentResolver.setMasterSyncAutomatically(true)));
// android.permission.WRITE_USER_DICTIONARY has been removed.
// new install permissions for Q
mPermissionTasks.put(REQUEST_PASSWORD_COMPLEXITY,
new PermissionTest(false, Build.VERSION_CODES.Q,
() -> mDevicePolicyManager.getPasswordComplexity()));
mPermissionTasks.put(USE_FULL_SCREEN_INTENT,
new PermissionTest(false, Build.VERSION_CODES.Q, () -> {
Intent notificationIntent = new Intent(mContext, MainActivity.class);
PendingIntent pendingIntent =
PendingIntent.getActivity(mContext, 0, notificationIntent, 0);
Resources resources = mContext.getResources();
CharSequence channelName = resources.getString(R.string.tester_channel_name);
NotificationChannel channel = new NotificationChannel(TAG, channelName,
NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager notificationManager = mContext.getSystemService(
NotificationManager.class);
notificationManager.createNotificationChannel(channel);
Notification notification =
new Notification.Builder(mContext, TAG)
.setContentTitle(resources.getText(
R.string.full_screen_intent_notification_title))
.setContentText(resources.getText(
R.string.full_screen_intent_notification_message))
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentIntent(pendingIntent)
.setFullScreenIntent(pendingIntent, false)
.build();
notificationManager.notify(0, notification);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
mLogger.logError("Caught an InterruptedException: " + e);
}
StatusBarNotification[] notifications =
notificationManager.getActiveNotifications();
if (notifications.length == 0) {
throw new SecurityException(
"fullScreenIntent not displayed as an active notification");
}
for (StatusBarNotification statusBarNotification : notifications) {
if (statusBarNotification.getNotification().fullScreenIntent == null) {
throw new SecurityException(
"fullScreenIntent field cleared after launching notification");
}
}
}));
// new install permissions for R
mPermissionTasks.put(NFC_PREFERRED_PAYMENT_INFO,
new PermissionTest(false, Build.VERSION_CODES.R, () -> {
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
if (adapter == null) {
throw new BypassTestException(
"An NFC adapter is not available to run this test");
}
CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
cardEmulation.getDescriptionForPreferredPaymentService();
}));
mPermissionTasks.put(QUERY_ALL_PACKAGES,
new PermissionTest(false, Build.VERSION_CODES.R, () -> {
try {
// The companion package should be installed to act as a queryable package
// for this test; without a <queries> tag in the AndroidManifest and without
// this permission granted a query for the companion package should result
// in a NameNotFoundException.
PackageInfo packageInfo = mPackageManager.getPackageInfo(
Constants.COMPANION_PACKAGE, 0);
} catch (PackageManager.NameNotFoundException e) {
throw new SecurityException(e);
}
}));
}