Merge branch 'dev/11/fp3/security-aosp-rvc-release' into int/11/fp3
* dev/11/fp3/security-aosp-rvc-release:
RESTRICT AUTOMERGE: Catch exceptions from setLockCredential()
Restrict ApnEditor settings
DO NOT MERGE: Prevent non-system IME from becoming device admin
Settings: don't try to allow NLSes with too-long component names
DO NOT MERGE Don't hide approved NLSes in Settings
Change-Id: I4147af6331399be28cc277d0464ed8fd4a2fb964
diff --git a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java
index 113922e..59ec178 100644
--- a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java
+++ b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java
@@ -50,6 +50,8 @@
import android.util.EventLog;
import android.util.Log;
import android.view.Display;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
@@ -138,7 +140,7 @@
mAppOps = (AppOpsManager)getSystemService(Context.APP_OPS_SERVICE);
PackageManager packageManager = getPackageManager();
- if ((getIntent().getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+ if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Log.w(TAG, "Cannot start ADD_DEVICE_ADMIN as a new task");
finish();
return;
@@ -148,7 +150,7 @@
EXTRA_CALLED_FROM_SUPPORT_DIALOG, false);
String action = getIntent().getAction();
- ComponentName who = (ComponentName)getIntent().getParcelableExtra(
+ ComponentName who = (ComponentName) getIntent().getParcelableExtra(
DevicePolicyManager.EXTRA_DEVICE_ADMIN);
if (who == null) {
String packageName = getIntent().getStringExtra(EXTRA_DEVICE_ADMIN_PACKAGE_NAME);
@@ -206,7 +208,7 @@
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
int count = avail == null ? 0 : avail.size();
boolean found = false;
- for (int i=0; i<count; i++) {
+ for (int i = 0; i < count; i++) {
ResolveInfo ri = avail.get(i);
if (ai.packageName.equals(ri.activityInfo.packageName)
&& ai.name.equals(ri.activityInfo.name)) {
@@ -337,12 +339,12 @@
}
setContentView(R.layout.device_admin_add);
- mAdminIcon = (ImageView)findViewById(R.id.admin_icon);
- mAdminName = (TextView)findViewById(R.id.admin_name);
- mAdminDescription = (TextView)findViewById(R.id.admin_description);
+ mAdminIcon = (ImageView) findViewById(R.id.admin_icon);
+ mAdminName = (TextView) findViewById(R.id.admin_name);
+ mAdminDescription = (TextView) findViewById(R.id.admin_description);
mProfileOwnerWarning = (TextView) findViewById(R.id.profile_owner_warning);
- mAddMsg = (TextView)findViewById(R.id.add_msg);
+ mAddMsg = (TextView) findViewById(R.id.add_msg);
mAddMsgExpander = (ImageView) findViewById(R.id.add_msg_expander);
final View.OnClickListener onClickListener = new View.OnClickListener() {
@Override
@@ -363,7 +365,7 @@
boolean hideMsgExpander = mAddMsg.getLineCount() <= maxLines;
mAddMsgExpander.setVisibility(hideMsgExpander ? View.GONE : View.VISIBLE);
if (hideMsgExpander) {
- ((View)mAddMsgExpander.getParent()).invalidate();
+ ((View) mAddMsgExpander.getParent()).invalidate();
}
mAddMsg.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
@@ -381,7 +383,7 @@
mCancelButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
EventLog.writeEvent(EventLogTags.EXP_DET_DEVICE_ADMIN_DECLINED_BY_USER,
- mDeviceAdmin.getActivityInfo().applicationInfo.uid);
+ mDeviceAdmin.getActivityInfo().applicationInfo.uid);
finish();
}
});
@@ -401,58 +403,64 @@
final View restrictedAction = findViewById(R.id.restricted_action);
restrictedAction.setFilterTouchesWhenObscured(true);
- restrictedAction.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) {
- if (!mActionButton.isEnabled()) {
- showPolicyTransparencyDialogIfRequired();
- return;
- }
- if (mAdding) {
- addAndFinish();
- } else if (isManagedProfile(mDeviceAdmin)
- && mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner())) {
- final int userId = UserHandle.myUserId();
- UserDialogs.createRemoveDialog(DeviceAdminAdd.this, userId,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- UserManager um = UserManager.get(DeviceAdminAdd.this);
- um.removeUser(userId);
- finish();
- }
- }
- ).show();
- } else if (mUninstalling) {
- mDPM.uninstallPackageWithActiveAdmins(mDeviceAdmin.getPackageName());
- finish();
- } else if (!mWaitingForRemoveMsg) {
- try {
- // Don't allow the admin to put a dialog up in front
- // of us while we interact with the user.
- ActivityManager.getService().stopAppSwitches();
- } catch (RemoteException e) {
- }
- mWaitingForRemoveMsg = true;
- mDPM.getRemoveWarning(mDeviceAdmin.getComponent(),
- new RemoteCallback(new RemoteCallback.OnResultListener() {
- @Override
- public void onResult(Bundle result) {
- CharSequence msg = result != null
- ? result.getCharSequence(
- DeviceAdminReceiver.EXTRA_DISABLE_WARNING)
- : null;
- continueRemoveAction(msg);
- }
- }, mHandler));
- // Don't want to wait too long.
- getWindow().getDecorView().getHandler().postDelayed(new Runnable() {
- @Override public void run() {
- continueRemoveAction(null);
- }
- }, 2*1000);
- }
+
+ final View.OnClickListener restrictedActionClickListener = v -> {
+ if (!mActionButton.isEnabled()) {
+ showPolicyTransparencyDialogIfRequired();
+ return;
}
+ if (mAdding) {
+ addAndFinish();
+ } else if (isManagedProfile(mDeviceAdmin)
+ && mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner())) {
+ final int userId = UserHandle.myUserId();
+ UserDialogs.createRemoveDialog(DeviceAdminAdd.this, userId,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ UserManager um = UserManager.get(DeviceAdminAdd.this);
+ um.removeUser(userId);
+ finish();
+ }
+ }
+ ).show();
+ } else if (mUninstalling) {
+ mDPM.uninstallPackageWithActiveAdmins(mDeviceAdmin.getPackageName());
+ finish();
+ } else if (!mWaitingForRemoveMsg) {
+ try {
+ // Don't allow the admin to put a dialog up in front
+ // of us while we interact with the user.
+ ActivityManager.getService().stopAppSwitches();
+ } catch (RemoteException e) {
+ }
+ mWaitingForRemoveMsg = true;
+ mDPM.getRemoveWarning(mDeviceAdmin.getComponent(),
+ new RemoteCallback(new RemoteCallback.OnResultListener() {
+ @Override
+ public void onResult(Bundle result) {
+ CharSequence msg = result != null
+ ? result.getCharSequence(
+ DeviceAdminReceiver.EXTRA_DISABLE_WARNING)
+ : null;
+ continueRemoveAction(msg);
+ }
+ }, mHandler));
+ // Don't want to wait too long.
+ getWindow().getDecorView().getHandler().postDelayed(
+ () -> continueRemoveAction(null), 2 * 1000);
+ }
+ };
+ restrictedAction.setOnKeyListener((view, keyCode, keyEvent) -> {
+ if ((keyEvent.getFlags() & KeyEvent.FLAG_FROM_SYSTEM) == 0) {
+ Log.e(TAG, "Can not activate device-admin with KeyEvent from non-system app.");
+ // Consume event to suppress click.
+ return true;
+ }
+ // Fallback to view click handler.
+ return false;
});
+ restrictedAction.setOnClickListener(restrictedActionClickListener);
}
/**
diff --git a/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java b/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java
index 6a4c22e..c77c2b9 100644
--- a/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java
+++ b/src/com/android/settings/applications/specialaccess/notificationaccess/NotificationAccessDetails.java
@@ -181,7 +181,10 @@
public void updatePreference(SwitchPreference preference) {
final CharSequence label = mPackageInfo.applicationInfo.loadLabel(mPm);
+ final boolean isAllowedCn = mComponentName.flattenToShortString().length()
+ <= NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH;
preference.setChecked(isServiceEnabled(mComponentName));
+ preference.setEnabled(preference.isChecked() || isAllowedCn);
preference.setOnPreferenceChangeListener((p, newValue) -> {
final boolean access = (Boolean) newValue;
if (!access) {
diff --git a/src/com/android/settings/network/ApnEditor.java b/src/com/android/settings/network/ApnEditor.java
index 9ab30cc..0cc8196 100644
--- a/src/com/android/settings/network/ApnEditor.java
+++ b/src/com/android/settings/network/ApnEditor.java
@@ -25,6 +25,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.PersistableBundle;
+import android.os.UserManager;
import android.provider.Telephony;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
@@ -287,6 +288,11 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ if (isUserRestricted()) {
+ Log.e(TAG, "This setting isn't available due to user restriction.");
+ finish();
+ return;
+ }
setLifecycleForAllControllers();
@@ -1418,6 +1424,23 @@
}
}
+ @VisibleForTesting
+ boolean isUserRestricted() {
+ UserManager userManager = getContext().getSystemService(UserManager.class);
+ if (userManager == null) {
+ return false;
+ }
+ if (!userManager.isAdminUser()) {
+ Log.e(TAG, "User is not an admin");
+ return true;
+ }
+ if (userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
+ Log.e(TAG, "User is not allowed to configure mobile network");
+ return true;
+ }
+ return false;
+ }
+
public static class ErrorDialog extends InstrumentedDialogFragment {
public static void showError(ApnEditor editor) {
diff --git a/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java b/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java
index dfe6df2..a6b565a 100644
--- a/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java
+++ b/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java
@@ -67,7 +67,9 @@
mUserId = getIntent().getIntExtra(EXTRA_USER_ID, UserHandle.USER_NULL);
CharSequence mAppLabel;
- if (mComponentName == null || mComponentName.getPackageName() == null) {
+ if (mComponentName == null || mComponentName.getPackageName() == null
+ || mComponentName.flattenToString().length()
+ > NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH) {
finish();
return;
}
diff --git a/src/com/android/settings/notification/NotificationAccessSettings.java b/src/com/android/settings/notification/NotificationAccessSettings.java
index 71e58e4..20e019e 100644
--- a/src/com/android/settings/notification/NotificationAccessSettings.java
+++ b/src/com/android/settings/notification/NotificationAccessSettings.java
@@ -58,8 +58,6 @@
public class NotificationAccessSettings extends EmptyTextSettings {
private static final String TAG = "NotifAccessSettings";
- private static final int MAX_CN_LENGTH = 500;
-
private static final ManagedServiceSettings.Config CONFIG =
new ManagedServiceSettings.Config.Builder()
.setTag(TAG)
@@ -94,12 +92,6 @@
.setNoun(CONFIG.noun)
.setSetting(CONFIG.setting)
.setTag(CONFIG.tag)
- .setValidator(info -> {
- if (info.getComponentName().flattenToString().length() > MAX_CN_LENGTH) {
- return false;
- }
- return true;
- })
.build();
mServiceListing.addCallback(this::updateList);
setPreferenceScreen(getPreferenceManager().createPreferenceScreen(mContext));
@@ -140,6 +132,12 @@
services.sort(new PackageItemInfo.DisplayNameComparator(mPm));
for (ServiceInfo service : services) {
final ComponentName cn = new ComponentName(service.packageName, service.name);
+ boolean isAllowed = mNm.isNotificationListenerAccessGranted(cn);
+ if (!isAllowed && cn.flattenToString().length()
+ > NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH) {
+ continue;
+ }
+
CharSequence title = null;
try {
title = mPm.getApplicationInfoAsUser(
@@ -154,7 +152,7 @@
pref.setIcon(mIconDrawableFactory.getBadgedIcon(service, service.applicationInfo,
UserHandle.getUserId(service.applicationInfo.uid)));
pref.setKey(cn.flattenToString());
- pref.setSummary(mNm.isNotificationListenerAccessGranted(cn)
+ pref.setSummary(isAllowed
? R.string.app_permission_summary_allowed
: R.string.app_permission_summary_not_allowed);
if (managedProfileId != UserHandle.USER_NULL
diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java
index 19cc9c8..9571ff9 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -958,8 +958,13 @@
@Override
protected Pair<Boolean, Intent> saveAndVerifyInBackground() {
- final boolean success = mUtils.setLockCredential(
- mChosenPassword, mCurrentCredential, mUserId);
+ boolean success;
+ try {
+ success = mUtils.setLockCredential(mChosenPassword, mCurrentCredential, mUserId);
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Failed to set lockscreen credential", e);
+ success = false;
+ }
if (success) {
unifyProfileCredentialIfRequested();
}
diff --git a/src/com/android/settings/password/ChooseLockPattern.java b/src/com/android/settings/password/ChooseLockPattern.java
index 27fc9f0..61638cb 100644
--- a/src/com/android/settings/password/ChooseLockPattern.java
+++ b/src/com/android/settings/password/ChooseLockPattern.java
@@ -902,8 +902,13 @@
@Override
protected Pair<Boolean, Intent> saveAndVerifyInBackground() {
final int userId = mUserId;
- final boolean success = mUtils.setLockCredential(mChosenPattern, mCurrentCredential,
- userId);
+ boolean success;
+ try {
+ success = mUtils.setLockCredential(mChosenPattern, mCurrentCredential, userId);
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Failed to set lockscreen credential", e);
+ success = false;
+ }
if (success) {
unifyProfileCredentialIfRequested();
}
diff --git a/tests/robotests/src/com/android/settings/network/ApnEditorTest.java b/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
index 7ec1174..5879c7f 100644
--- a/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
+++ b/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
@@ -34,6 +34,7 @@
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
+import android.os.UserManager;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
@@ -101,6 +102,8 @@
@Mock
private FragmentActivity mActivity;
@Mock
+ private UserManager mUserManager;
+ @Mock
private ProxySubscriptionManager mProxySubscriptionMgr;
@Captor
@@ -126,6 +129,11 @@
doReturn(mContext.getTheme()).when(mActivity).getTheme();
doReturn(mContext.getContentResolver()).when(mActivity).getContentResolver();
+ doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
+ doReturn(true).when(mUserManager).isAdminUser();
+ doReturn(false).when(mUserManager)
+ .hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
+
setMockPreference(mContext);
mApnEditorUT.mApnData = new FakeApnData(APN_DATA);
mApnEditorUT.sNotSet = "Not Set";
@@ -452,6 +460,27 @@
@Test
@Config(shadows = ShadowFragment.class)
+ public void onCreate_notAdminUser_shouldFinish() {
+ doReturn(false).when(mUserManager).isAdminUser();
+
+ mApnEditorUT.onCreate(null);
+
+ verify(mApnEditorUT).finish();
+ }
+
+ @Test
+ @Config(shadows = ShadowFragment.class)
+ public void onCreate_hasUserRestriction_shouldFinish() {
+ doReturn(true).when(mUserManager)
+ .hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
+
+ mApnEditorUT.onCreate(null);
+
+ verify(mApnEditorUT).finish();
+ }
+
+ @Test
+ @Config(shadows = ShadowFragment.class)
public void onCreate_noAction_shouldFinishAndNoCrash() {
ProxySubscriptionManager proxySubscriptionMgr = mock(ProxySubscriptionManager.class);
mApnEditorUT.mProxySubscriptionMgr = proxySubscriptionMgr;