Skip to content

Commit 565e6d5

Browse files
committed
Merge remote-tracking branch 'BlissRoms/typhoon' into HEAD
2 parents 22870ce + 00ccb22 commit 565e6d5

7 files changed

Lines changed: 212 additions & 16 deletions

File tree

src/com/android/settings/DefaultRingtonePreference.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,9 @@ protected void onSaveRingtone(Uri ringtoneUri) {
5151
return;
5252
}
5353

54-
String mimeType = mUserContext.getContentResolver().getType(ringtoneUri);
55-
if (mimeType == null) {
54+
if (!isValidRingtoneUri(ringtoneUri)) {
5655
Log.e(TAG, "onSaveRingtone for URI:" + ringtoneUri
57-
+ " ignored: failure to find mimeType (no access from this context?)");
58-
return;
59-
}
60-
61-
if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg"))) {
62-
Log.e(TAG, "onSaveRingtone for URI:" + ringtoneUri
63-
+ " ignored: associated mimeType:" + mimeType + " is not an audio type");
56+
+ " ignored: invalid ringtone Uri");
6457
return;
6558
}
6659

src/com/android/settings/RingtonePreference.java

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,20 @@
1616

1717
package com.android.settings;
1818

19+
import android.content.ContentProvider;
20+
import android.content.ContentResolver;
1921
import android.content.Context;
2022
import android.content.Intent;
2123
import android.content.res.TypedArray;
2224
import android.media.AudioAttributes;
2325
import android.media.RingtoneManager;
2426
import android.net.Uri;
2527
import android.os.UserHandle;
28+
import android.os.UserManager;
2629
import android.provider.Settings.System;
2730
import android.text.TextUtils;
2831
import android.util.AttributeSet;
32+
import android.util.Log;
2933

3034
import androidx.preference.Preference;
3135
import androidx.preference.PreferenceManager;
@@ -239,4 +243,82 @@ public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
239243
return true;
240244
}
241245

246+
public boolean isDefaultRingtone(Uri ringtoneUri) {
247+
// null URIs are valid (None/silence)
248+
return ringtoneUri == null || RingtoneManager.isDefault(ringtoneUri);
249+
}
250+
251+
protected boolean isValidRingtoneUri(Uri ringtoneUri) {
252+
if (isDefaultRingtone(ringtoneUri)) {
253+
return true;
254+
}
255+
256+
// Return early for android resource URIs
257+
if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(ringtoneUri.getScheme())) {
258+
return true;
259+
}
260+
261+
String mimeType = mUserContext.getContentResolver().getType(ringtoneUri);
262+
if (mimeType == null) {
263+
Log.e(TAG, "isValidRingtoneUri for URI:" + ringtoneUri
264+
+ " failed: failure to find mimeType (no access from this context?)");
265+
return false;
266+
}
267+
268+
if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg")
269+
|| mimeType.equals("application/x-flac"))) {
270+
Log.e(TAG, "isValidRingtoneUri for URI:" + ringtoneUri
271+
+ " failed: associated mimeType:" + mimeType + " is not an audio type");
272+
return false;
273+
}
274+
275+
// Validate userId from URIs: content://{userId}@...
276+
final int userIdFromUri = ContentProvider.getUserIdFromUri(ringtoneUri, mUserId);
277+
if (userIdFromUri != mUserId) {
278+
final UserManager userManager = mUserContext.getSystemService(UserManager.class);
279+
280+
if (!userManager.isSameProfileGroup(mUserId, userIdFromUri)) {
281+
Log.e(TAG,
282+
"isValidRingtoneUri for URI:" + ringtoneUri + " failed: user " + userIdFromUri
283+
+ " and user " + mUserId + " are not in the same profile group");
284+
return false;
285+
}
286+
287+
final int parentUserId;
288+
final int profileUserId;
289+
if (userManager.isProfile()) {
290+
profileUserId = mUserId;
291+
parentUserId = userIdFromUri;
292+
} else {
293+
parentUserId = mUserId;
294+
profileUserId = userIdFromUri;
295+
}
296+
297+
final UserHandle parent = userManager.getProfileParent(UserHandle.of(profileUserId));
298+
if (parent == null || parent.getIdentifier() != parentUserId) {
299+
Log.e(TAG,
300+
"isValidRingtoneUri for URI:" + ringtoneUri + " failed: user " + profileUserId
301+
+ " is not a profile of user " + parentUserId);
302+
return false;
303+
}
304+
305+
// Allow parent <-> managed profile sharing, unless restricted
306+
if (userManager.hasUserRestrictionForUser(
307+
UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE, UserHandle.of(parentUserId))) {
308+
Log.e(TAG,
309+
"isValidRingtoneUri for URI:" + ringtoneUri + " failed: user " + parentUserId
310+
+ " has restriction: " + UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE);
311+
return false;
312+
}
313+
314+
if (!userManager.isManagedProfile(profileUserId)) {
315+
Log.e(TAG, "isValidRingtoneUri for URI:" + ringtoneUri
316+
+ " failed: user " + profileUserId + " is not a managed profile");
317+
return false;
318+
}
319+
}
320+
321+
return true;
322+
}
323+
242324
}

src/com/android/settings/notification/NotificationAccessConfirmationActivity.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package com.android.settings.notification;
1919

20+
import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_APPS_CANNOT_ACCESS_NOTIFICATION_SETTINGS;
2021
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
2122

2223
import static com.android.internal.notification.NotificationAccessConfirmationActivityContract.EXTRA_COMPONENT_NAME;
@@ -26,6 +27,7 @@
2627
import android.annotation.Nullable;
2728
import android.app.Activity;
2829
import android.app.NotificationManager;
30+
import android.app.admin.DevicePolicyManager;
2931
import android.content.ComponentName;
3032
import android.content.Context;
3133
import android.content.DialogInterface;
@@ -35,10 +37,12 @@
3537
import android.content.pm.ServiceInfo;
3638
import android.os.Bundle;
3739
import android.os.UserHandle;
40+
import android.os.UserManager;
3841
import android.text.TextUtils;
3942
import android.util.Slog;
4043
import android.view.WindowManager;
4144
import android.view.accessibility.AccessibilityEvent;
45+
import android.widget.Toast;
4246

4347
import com.android.internal.app.AlertActivity;
4448
import com.android.internal.app.AlertController;
@@ -55,12 +59,28 @@ public class NotificationAccessConfirmationActivity extends Activity
5559
private ComponentName mComponentName;
5660
private NotificationManager mNm;
5761

62+
private DevicePolicyManager mDpm;
63+
private UserManager mUm;
64+
5865
@Override
5966
protected void onCreate(@Nullable Bundle savedInstanceState) {
6067
super.onCreate(savedInstanceState);
6168

6269
getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
6370

71+
mUm = getSystemService(UserManager.class);
72+
mDpm = getSystemService(DevicePolicyManager.class);
73+
74+
if (mUm.isManagedProfile()) {
75+
Slog.w(LOG_TAG, "Apps in the work profile do not support notification listeners");
76+
Toast.makeText(this,
77+
mDpm.getResources().getString(WORK_APPS_CANNOT_ACCESS_NOTIFICATION_SETTINGS,
78+
() -> getString(R.string.notification_settings_work_profile)),
79+
Toast.LENGTH_SHORT).show();
80+
finish();
81+
return;
82+
}
83+
6484
mNm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
6585

6686
mComponentName = getIntent().getParcelableExtra(EXTRA_COMPONENT_NAME);

src/com/android/settings/notification/app/NotificationSoundPreference.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@
2525
import android.os.AsyncTask;
2626
import android.util.AttributeSet;
2727

28+
import android.util.Log;
2829
import com.android.settings.R;
2930
import com.android.settings.RingtonePreference;
3031

3132
public class NotificationSoundPreference extends RingtonePreference {
33+
private static final String TAG = "NotificationSoundPreference";
34+
3235
private Uri mRingtone;
3336

3437
public NotificationSoundPreference(Context context, AttributeSet attrs) {
@@ -50,8 +53,13 @@ public void setRingtone(Uri ringtone) {
5053
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
5154
if (data != null) {
5255
Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
53-
setRingtone(uri);
54-
callChangeListener(uri);
56+
if (isValidRingtoneUri(uri)) {
57+
setRingtone(uri);
58+
callChangeListener(uri);
59+
} else {
60+
Log.e(TAG, "onActivityResult for URI:" + uri
61+
+ " ignored: invalid ringtone Uri");
62+
}
5563
}
5664

5765
return true;

src/com/android/settings/wifi/WifiDialogActivity.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.android.settings.wifi;
1818

1919
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
20+
import static android.os.UserManager.DISALLOW_ADD_WIFI_CONFIG;
2021
import static android.os.UserManager.DISALLOW_CONFIG_WIFI;
2122

2223
import android.app.KeyguardManager;
@@ -122,7 +123,7 @@ protected void onCreate(Bundle savedInstanceState) {
122123
}
123124

124125
super.onCreate(savedInstanceState);
125-
if (!isConfigWifiAllowed()) {
126+
if (!isConfigWifiAllowed() || !isAddWifiConfigAllowed()) {
126127
finish();
127128
return;
128129
}
@@ -393,6 +394,16 @@ boolean isConfigWifiAllowed() {
393394
return isConfigWifiAllowed;
394395
}
395396

397+
@VisibleForTesting
398+
boolean isAddWifiConfigAllowed() {
399+
UserManager userManager = getSystemService(UserManager.class);
400+
if (userManager != null && userManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)) {
401+
Log.e(TAG, "The user is not allowed to add Wi-Fi configuration.");
402+
return false;
403+
}
404+
return true;
405+
}
406+
396407
private boolean hasWifiManager() {
397408
if (mWifiManager != null) return true;
398409
mWifiManager = getSystemService(WifiManager.class);

tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
2020
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
21+
import static android.os.UserManager.DISALLOW_ADD_WIFI_CONFIG;
2122
import static android.os.UserManager.DISALLOW_CONFIG_WIFI;
2223

2324
import static com.android.settings.wifi.WifiDialogActivity.REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER;
@@ -234,6 +235,20 @@ public void isConfigWifiAllowed_hasUserRestriction_returnFalse() {
234235
assertThat(mActivity.isConfigWifiAllowed()).isFalse();
235236
}
236237

238+
@Test
239+
public void isAddWifiConfigAllowed_hasNoUserRestriction_returnTrue() {
240+
when(mUserManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)).thenReturn(false);
241+
242+
assertThat(mActivity.isAddWifiConfigAllowed()).isTrue();
243+
}
244+
245+
@Test
246+
public void isAddWifiConfigAllowed_hasUserRestriction_returnFalse() {
247+
when(mUserManager.hasUserRestriction(DISALLOW_ADD_WIFI_CONFIG)).thenReturn(true);
248+
249+
assertThat(mActivity.isAddWifiConfigAllowed()).isFalse();
250+
}
251+
237252
@Test
238253
public void hasPermissionForResult_noCallingPackage_returnFalse() {
239254
when(mActivity.getCallingPackage()).thenReturn(null);

tests/unit/src/com/android/settings/DefaultRingtonePreferenceTest.java

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,19 @@
1616

1717
package com.android.settings;
1818

19+
import static org.mockito.ArgumentMatchers.any;
1920
import static org.mockito.Mockito.doReturn;
2021
import static org.mockito.Mockito.never;
2122
import static org.mockito.Mockito.spy;
2223
import static org.mockito.Mockito.verify;
2324
import static org.mockito.Mockito.when;
2425

26+
import android.content.ContentInterface;
2527
import android.content.ContentResolver;
2628
import android.content.Context;
27-
import android.media.RingtoneManager;
2829
import android.net.Uri;
30+
import android.os.UserHandle;
31+
import android.os.UserManager;
2932

3033
import androidx.test.core.app.ApplicationProvider;
3134
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -34,32 +37,47 @@
3437
import org.junit.Test;
3538
import org.junit.runner.RunWith;
3639
import org.mockito.Mock;
40+
import org.mockito.Mockito;
3741
import org.mockito.MockitoAnnotations;
3842

3943
/** Unittest for DefaultRingtonePreference. */
4044
@RunWith(AndroidJUnit4.class)
4145
public class DefaultRingtonePreferenceTest {
4246

47+
private static final int OWNER_USER_ID = 1;
48+
private static final int OTHER_USER_ID = 10;
49+
private static final int INVALID_RINGTONE_TYPE = 0;
4350
private DefaultRingtonePreference mDefaultRingtonePreference;
4451

4552
@Mock
4653
private ContentResolver mContentResolver;
4754
@Mock
55+
private UserManager mUserManager;
4856
private Uri mRingtoneUri;
4957

5058
@Before
5159
public void setUp() {
5260
MockitoAnnotations.initMocks(this);
5361

5462
Context context = spy(ApplicationProvider.getApplicationContext());
55-
doReturn(mContentResolver).when(context).getContentResolver();
63+
mContentResolver = ContentResolver.wrap(Mockito.mock(ContentInterface.class));
64+
when(context.getContentResolver()).thenReturn(mContentResolver);
5665

5766
mDefaultRingtonePreference = spy(new DefaultRingtonePreference(context, null /* attrs */));
5867
doReturn(context).when(mDefaultRingtonePreference).getContext();
68+
69+
// Use INVALID_RINGTONE_TYPE to return early in RingtoneManager.setActualDefaultRingtoneUri
5970
when(mDefaultRingtonePreference.getRingtoneType())
60-
.thenReturn(RingtoneManager.TYPE_RINGTONE);
61-
mDefaultRingtonePreference.setUserId(1);
71+
.thenReturn(INVALID_RINGTONE_TYPE);
72+
73+
mDefaultRingtonePreference.setUserId(OWNER_USER_ID);
6274
mDefaultRingtonePreference.mUserContext = context;
75+
when(mDefaultRingtonePreference.isDefaultRingtone(any(Uri.class))).thenReturn(false);
76+
77+
when(context.getSystemServiceName(UserManager.class)).thenReturn(Context.USER_SERVICE);
78+
when(context.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
79+
80+
mRingtoneUri = Uri.parse("content://none");
6381
}
6482

6583
@Test
@@ -79,4 +97,53 @@ public void onSaveRingtone_notAudioMimeType_shouldNotSetRingtone() {
7997

8098
verify(mDefaultRingtonePreference, never()).setActualDefaultRingtoneUri(mRingtoneUri);
8199
}
100+
101+
@Test
102+
public void onSaveRingtone_notManagedProfile_shouldNotSetRingtone() {
103+
mRingtoneUri = Uri.parse("content://" + OTHER_USER_ID + "@ringtone");
104+
when(mContentResolver.getType(mRingtoneUri)).thenReturn("audio/*");
105+
when(mUserManager.isSameProfileGroup(OWNER_USER_ID, OTHER_USER_ID)).thenReturn(true);
106+
when(mUserManager.getProfileParent(UserHandle.of(OTHER_USER_ID))).thenReturn(
107+
UserHandle.of(OWNER_USER_ID));
108+
when(mUserManager.isManagedProfile(OTHER_USER_ID)).thenReturn(false);
109+
110+
mDefaultRingtonePreference.onSaveRingtone(mRingtoneUri);
111+
112+
verify(mDefaultRingtonePreference, never()).setActualDefaultRingtoneUri(mRingtoneUri);
113+
}
114+
115+
@Test
116+
public void onSaveRingtone_notSameUser_shouldNotSetRingtone() {
117+
mRingtoneUri = Uri.parse("content://" + OTHER_USER_ID + "@ringtone");
118+
when(mContentResolver.getType(mRingtoneUri)).thenReturn("audio/*");
119+
when(mUserManager.isSameProfileGroup(OWNER_USER_ID, OTHER_USER_ID)).thenReturn(false);
120+
121+
mDefaultRingtonePreference.onSaveRingtone(mRingtoneUri);
122+
123+
verify(mDefaultRingtonePreference, never()).setActualDefaultRingtoneUri(mRingtoneUri);
124+
}
125+
126+
@Test
127+
public void onSaveRingtone_isManagedProfile_shouldSetRingtone() {
128+
mRingtoneUri = Uri.parse("content://" + OTHER_USER_ID + "@ringtone");
129+
when(mContentResolver.getType(mRingtoneUri)).thenReturn("audio/*");
130+
when(mUserManager.isSameProfileGroup(OWNER_USER_ID, OTHER_USER_ID)).thenReturn(true);
131+
when(mUserManager.getProfileParent(UserHandle.of(OTHER_USER_ID))).thenReturn(
132+
UserHandle.of(OWNER_USER_ID));
133+
when(mUserManager.isManagedProfile(OTHER_USER_ID)).thenReturn(true);
134+
135+
mDefaultRingtonePreference.onSaveRingtone(mRingtoneUri);
136+
137+
verify(mDefaultRingtonePreference).setActualDefaultRingtoneUri(mRingtoneUri);
138+
}
139+
140+
@Test
141+
public void onSaveRingtone_defaultUri_shouldSetRingtone() {
142+
mRingtoneUri = Uri.parse("default_ringtone");
143+
when(mDefaultRingtonePreference.isDefaultRingtone(any(Uri.class))).thenReturn(true);
144+
145+
mDefaultRingtonePreference.onSaveRingtone(mRingtoneUri);
146+
147+
verify(mDefaultRingtonePreference).setActualDefaultRingtoneUri(mRingtoneUri);
148+
}
82149
}

0 commit comments

Comments
 (0)