Merge "[Settings] Move display of VPN version into summary text" into rvc-dev
diff --git a/src/com/android/settings/connecteddevice/NfcAndPaymentFragment.java b/src/com/android/settings/connecteddevice/NfcAndPaymentFragment.java
index 4ebc0cd..feb757f 100644
--- a/src/com/android/settings/connecteddevice/NfcAndPaymentFragment.java
+++ b/src/com/android/settings/connecteddevice/NfcAndPaymentFragment.java
@@ -17,6 +17,12 @@
package com.android.settings.connecteddevice;
import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
@@ -54,5 +60,16 @@
* For Search.
*/
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
- new BaseSearchIndexProvider(R.xml.nfc_and_payment_settings);
+ new BaseSearchIndexProvider(R.xml.nfc_and_payment_settings) {
+ @Override
+ protected boolean isPageSearchEnabled(Context context) {
+ final UserManager userManager = context.getSystemService(UserManager.class);
+ final UserInfo myUserInfo = userManager.getUserInfo(UserHandle.myUserId());
+ if (myUserInfo.isGuest()) {
+ return false;
+ }
+ final PackageManager pm = context.getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_NFC);
+ }
+ };
}
diff --git a/src/com/android/settings/network/PrivateDnsPreferenceController.java b/src/com/android/settings/network/PrivateDnsPreferenceController.java
index 84cae88..22633e0 100644
--- a/src/com/android/settings/network/PrivateDnsPreferenceController.java
+++ b/src/com/android/settings/network/PrivateDnsPreferenceController.java
@@ -84,9 +84,12 @@
@Override
public int getAvailabilityStatus() {
- return mContext.getResources().getBoolean(R.bool.config_show_private_dns_settings)
- ? AVAILABLE
- : UNSUPPORTED_ON_DEVICE;
+ if (!mContext.getResources().getBoolean(R.bool.config_show_private_dns_settings)) {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+ final UserManager userManager = mContext.getSystemService(UserManager.class);
+ if (userManager.isGuestUser()) return DISABLED_FOR_USER;
+ return AVAILABLE;
}
@Override
diff --git a/src/com/android/settings/nfc/SecureNfcEnabler.java b/src/com/android/settings/nfc/SecureNfcEnabler.java
index 9acaf64..f31a382 100644
--- a/src/com/android/settings/nfc/SecureNfcEnabler.java
+++ b/src/com/android/settings/nfc/SecureNfcEnabler.java
@@ -18,9 +18,8 @@
import android.content.Context;
import android.nfc.NfcAdapter;
-import android.provider.Settings;
+import android.os.UserManager;
-import androidx.annotation.VisibleForTesting;
import androidx.preference.SwitchPreference;
import com.android.settings.R;
@@ -32,10 +31,12 @@
*/
public class SecureNfcEnabler extends BaseNfcEnabler {
private final SwitchPreference mPreference;
+ private final UserManager mUserManager;
public SecureNfcEnabler(Context context, SwitchPreference preference) {
super(context);
mPreference = preference;
+ mUserManager = context.getSystemService(UserManager.class);
}
@Override
@@ -48,7 +49,7 @@
case NfcAdapter.STATE_ON:
mPreference.setSummary(R.string.nfc_secure_toggle_summary);
mPreference.setChecked(mPreference.isChecked());
- mPreference.setEnabled(true);
+ mPreference.setEnabled(isToggleable());
break;
case NfcAdapter.STATE_TURNING_ON:
mPreference.setEnabled(false);
@@ -58,4 +59,11 @@
break;
}
}
+
+ private boolean isToggleable() {
+ if (mUserManager.isGuestUser()) {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/src/com/android/settings/security/CredentialStorage.java b/src/com/android/settings/security/CredentialStorage.java
index 5e64723..23913ce 100644
--- a/src/com/android/settings/security/CredentialStorage.java
+++ b/src/com/android/settings/security/CredentialStorage.java
@@ -85,7 +85,7 @@
final String action = intent.getAction();
final UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
if (!userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) {
- if (ACTION_RESET.equals(action)) {
+ if (ACTION_RESET.equals(action) && checkCallerIsSelf()) {
new ResetDialog();
} else {
if (ACTION_INSTALL.equals(action) && checkCallerIsCertInstallerOrSelfInProfile()) {
@@ -318,6 +318,19 @@
}
/**
+ * Check that the caller is Settings.
+ */
+ private boolean checkCallerIsSelf() {
+ try {
+ return Process.myUid() == android.app.ActivityManager.getService()
+ .getLaunchedFromUid(getActivityToken());
+ } catch (RemoteException re) {
+ // Error talking to ActivityManager, just give up
+ return false;
+ }
+ }
+
+ /**
* Check that the caller is either certinstaller or Settings running in a profile of this user.
*/
private boolean checkCallerIsCertInstallerOrSelfInProfile() {
diff --git a/src/com/android/settings/security/InstallCaCertificateWarning.java b/src/com/android/settings/security/InstallCaCertificateWarning.java
index 91faae1..b5cc6b3 100644
--- a/src/com/android/settings/security/InstallCaCertificateWarning.java
+++ b/src/com/android/settings/security/InstallCaCertificateWarning.java
@@ -16,6 +16,8 @@
package com.android.settings.security;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
import android.annotation.Nullable;
import android.app.Activity;
import android.content.Intent;
@@ -41,6 +43,8 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.ca_certificate_warning_dialog);
+ getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+
final GlifLayout layout = findViewById(R.id.setup_wizard_layout);
final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
@@ -52,6 +56,7 @@
.setTheme(R.style.SudGlifButton_Secondary)
.build()
);
+ mixin.getSecondaryButtonView().setFilterTouchesWhenObscured(true);
mixin.setPrimaryButton(
new FooterButton.Builder(this)
@@ -61,6 +66,7 @@
.setTheme(R.style.SudGlifButton_Primary)
.build()
);
+ mixin.getPrimaryButtonView().setFilterTouchesWhenObscured(true);
}
private View.OnClickListener installCaCertificate() {
diff --git a/src/com/android/settings/users/AppRestrictionsFragment.java b/src/com/android/settings/users/AppRestrictionsFragment.java
index 9f6a2b6..1d3d9eb 100644
--- a/src/com/android/settings/users/AppRestrictionsFragment.java
+++ b/src/com/android/settings/users/AppRestrictionsFragment.java
@@ -18,6 +18,7 @@
import android.app.Activity;
import android.app.settings.SettingsEnums;
+import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -37,6 +38,7 @@
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.EventLog;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
@@ -641,7 +643,15 @@
} else if (restrictionsIntent != null) {
preference.setRestrictions(restrictions);
if (invokeIfCustom && AppRestrictionsFragment.this.isResumed()) {
- assertSafeToStartCustomActivity(restrictionsIntent);
+ try {
+ assertSafeToStartCustomActivity(restrictionsIntent);
+ } catch (ActivityNotFoundException | SecurityException e) {
+ // return without startActivity
+ Log.e(TAG, "Cannot start restrictionsIntent " + e);
+ EventLog.writeEvent(0x534e4554, "200688991", -1 /* UID */, "");
+ return;
+ }
+
int requestCode = generateCustomActivityRequestCode(
RestrictionsResultReceiver.this.preference);
AppRestrictionsFragment.this.startActivityForResult(
@@ -655,14 +665,14 @@
if (intent.getPackage() != null && intent.getPackage().equals(packageName)) {
return;
}
- // Activity can be started if intent resolves to multiple activities
- List<ResolveInfo> resolveInfos = AppRestrictionsFragment.this.mPackageManager
- .queryIntentActivities(intent, 0 /* no flags */);
- if (resolveInfos.size() != 1) {
- return;
+ ResolveInfo resolveInfo = mPackageManager.resolveActivity(
+ intent, PackageManager.MATCH_DEFAULT_ONLY);
+
+ if (resolveInfo == null) {
+ throw new ActivityNotFoundException("No result for resolving " + intent);
}
// Prevent potential privilege escalation
- ActivityInfo activityInfo = resolveInfos.get(0).activityInfo;
+ ActivityInfo activityInfo = resolveInfo.activityInfo;
if (!packageName.equals(activityInfo.packageName)) {
throw new SecurityException("Application " + packageName
+ " is not allowed to start activity " + intent);
diff --git a/src/com/android/settings/users/EditUserPhotoController.java b/src/com/android/settings/users/EditUserPhotoController.java
index 60f720e..bd698c2 100644
--- a/src/com/android/settings/users/EditUserPhotoController.java
+++ b/src/com/android/settings/users/EditUserPhotoController.java
@@ -21,6 +21,8 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
@@ -77,6 +79,7 @@
private static final int REQUEST_CODE_TAKE_PHOTO = 1002;
private static final int REQUEST_CODE_CROP_PHOTO = 1003;
+ private static final String PRE_CROP_PICTURE_FILE_NAME = "PreCropEditUserPhoto.jpg";
private static final String CROP_PICTURE_FILE_NAME = "CropEditUserPhoto.jpg";
private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto2.jpg";
private static final String NEW_USER_PHOTO_FILE_NAME = "NewUserPhoto.png";
@@ -87,6 +90,7 @@
private final Fragment mFragment;
private final ImageView mImageView;
+ private final Uri mPreCropPictureUri;
private final Uri mCropPictureUri;
private final Uri mTakePictureUri;
@@ -98,6 +102,8 @@
mContext = view.getContext();
mFragment = fragment;
mImageView = view;
+
+ mPreCropPictureUri = createTempImageUri(mContext, PRE_CROP_PICTURE_FILE_NAME, !waiting);
mCropPictureUri = createTempImageUri(mContext, CROP_PICTURE_FILE_NAME, !waiting);
mTakePictureUri = createTempImageUri(mContext, TAKE_PICTURE_FILE_NAME, !waiting);
mPhotoSize = getPhotoSize(mContext);
@@ -132,7 +138,7 @@
case REQUEST_CODE_TAKE_PHOTO:
case REQUEST_CODE_CHOOSE_PHOTO:
if (mTakePictureUri.equals(pictureUri)) {
- cropPhoto();
+ cropPhoto(pictureUri);
} else {
copyAndCropPhoto(pictureUri);
}
@@ -228,7 +234,7 @@
protected Void doInBackground(Void... params) {
final ContentResolver cr = mContext.getContentResolver();
try (InputStream in = cr.openInputStream(pictureUri);
- OutputStream out = cr.openOutputStream(mTakePictureUri)) {
+ OutputStream out = cr.openOutputStream(mPreCropPictureUri)) {
Streams.copy(in, out);
} catch (IOException e) {
Log.w(TAG, "Failed to copy photo", e);
@@ -239,27 +245,38 @@
@Override
protected void onPostExecute(Void result) {
if (!mFragment.isAdded()) return;
- cropPhoto();
+ cropPhoto(mPreCropPictureUri);
}
}.execute();
}
- private void cropPhoto() {
+ private void cropPhoto(final Uri pictureUri) {
// TODO: Use a public intent, when there is one.
Intent intent = new Intent("com.android.camera.action.CROP");
- intent.setDataAndType(mTakePictureUri, "image/*");
+ intent.setDataAndType(pictureUri, "image/*");
appendOutputExtra(intent, mCropPictureUri);
appendCropExtras(intent);
- if (intent.resolveActivity(mContext.getPackageManager()) != null) {
- try {
- StrictMode.disableDeathOnFileUriExposure();
- mFragment.startActivityForResult(intent, REQUEST_CODE_CROP_PHOTO);
- } finally {
- StrictMode.enableDeathOnFileUriExposure();
+ try {
+ StrictMode.disableDeathOnFileUriExposure();
+ if (startSystemActivityForResult(intent, REQUEST_CODE_CROP_PHOTO)) {
+ return;
}
- } else {
- onPhotoCropped(mTakePictureUri, false);
+ } finally {
+ StrictMode.enableDeathOnFileUriExposure();
}
+ onPhotoCropped(mTakePictureUri, false);
+ }
+
+ private boolean startSystemActivityForResult(Intent intent, int code) {
+ ActivityInfo info = intent.resolveActivityInfo(mContext.getPackageManager(),
+ PackageManager.MATCH_SYSTEM_ONLY);
+ if (info == null) {
+ Log.w(TAG, "No system package activity could be found for code " + code);
+ return false;
+ }
+ intent.setPackage(info.packageName);
+ mFragment.startActivityForResult(intent, code);
+ return true;
}
private void appendOutputExtra(Intent intent, Uri pictureUri) {
diff --git a/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java
index efb77eb..1eeffde 100644
--- a/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/PrivateDnsPreferenceControllerTest.java
@@ -27,6 +27,7 @@
import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.google.common.truth.Truth.assertThat;
@@ -36,6 +37,7 @@
import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
@@ -109,6 +111,8 @@
private Network mNetwork;
@Mock
private Preference mPreference;
+ @Mock
+ private UserManager mUserManager;
@Captor
private ArgumentCaptor<NetworkCallback> mCallbackCaptor;
private PrivateDnsPreferenceController mController;
@@ -127,6 +131,7 @@
mShadowContentResolver = Shadow.extract(mContentResolver);
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
.thenReturn(mConnectivityManager);
+ when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
doNothing().when(mConnectivityManager).registerDefaultNetworkCallback(
mCallbackCaptor.capture(), nullable(Handler.class));
@@ -174,6 +179,12 @@
}
@Test
+ public void getAvailabilityStatus_disabledForGuestUser() {
+ doReturn(true).when(mUserManager).isGuestUser();
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_FOR_USER);
+ }
+
+ @Test
public void goThroughLifecycle_shouldRegisterUnregisterSettingsObserver() {
mLifecycle.handleLifecycleEvent(ON_START);
verify(mContext, atLeastOnce()).getContentResolver();