From 640eab60f2baa9052d395fccd4a0324103ad6c7a Mon Sep 17 00:00:00 2001 From: Arc Wang Date: Fri, 6 May 2022 17:42:30 +0800 Subject: [PATCH] [DO NOT MERGE] Verify ringtone from ringtone picker is audio To improve privacy. Bug: 221041256 Test: atest com.android.settings.DefaultRingtonePreferenceTest Change-Id: I0a9ca163f5ae91b67c9f957fde4c6db326b8718d Merged-In: I0a9ca163f5ae91b67c9f957fde4c6db326b8718d (cherry picked from commit e4c22580c9a66a3d5523782c2daa707531210227) --- .../settings/DefaultRingtonePreference.java | 21 +++++ tests/unit/Android.mk | 2 + .../DefaultRingtonePreferenceTest.java | 81 +++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 tests/unit/src/com/android/settings/DefaultRingtonePreferenceTest.java diff --git a/src/com/android/settings/DefaultRingtonePreference.java b/src/com/android/settings/DefaultRingtonePreference.java index 9f9f832b100..914c4b214d1 100644 --- a/src/com/android/settings/DefaultRingtonePreference.java +++ b/src/com/android/settings/DefaultRingtonePreference.java @@ -22,6 +22,9 @@ import android.content.Intent; import android.media.RingtoneManager; import android.net.Uri; import android.util.AttributeSet; +import android.util.Log; + +import androidx.annotation.VisibleForTesting; public class DefaultRingtonePreference extends RingtonePreference { private static final String TAG = "DefaultRingtonePreference"; @@ -43,6 +46,24 @@ public class DefaultRingtonePreference extends RingtonePreference { @Override protected void onSaveRingtone(Uri ringtoneUri) { + String mimeType = getContext().getContentResolver().getType(ringtoneUri); + if (mimeType == null) { + Log.e(TAG, "onSaveRingtone for URI:" + ringtoneUri + + " ignored: failure to find mimeType (no access from this context?)"); + return; + } + + if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg"))) { + Log.e(TAG, "onSaveRingtone for URI:" + ringtoneUri + + " ignored: associated mimeType:" + mimeType + " is not an audio type"); + return; + } + + setActualDefaultRingtoneUri(ringtoneUri); + } + + @VisibleForTesting + void setActualDefaultRingtoneUri(Uri ringtoneUri) { RingtoneManager.setActualDefaultRingtoneUri(mUserContext, getRingtoneType(), ringtoneUri); } diff --git a/tests/unit/Android.mk b/tests/unit/Android.mk index 35d220532be..c643c755381 100644 --- a/tests/unit/Android.mk +++ b/tests/unit/Android.mk @@ -14,10 +14,12 @@ LOCAL_JAVA_LIBRARIES := \ LOCAL_STATIC_JAVA_LIBRARIES := \ + androidx.test.core \ androidx.test.rules \ androidx.test.espresso.core \ androidx.test.espresso.contrib-nodeps \ androidx.test.espresso.intents-nodeps \ + androidx.test.ext.junit \ mockito-target-minus-junit4 \ platform-test-annotations \ truth-prebuilt \ diff --git a/tests/unit/src/com/android/settings/DefaultRingtonePreferenceTest.java b/tests/unit/src/com/android/settings/DefaultRingtonePreferenceTest.java new file mode 100644 index 00000000000..b9dea0167b5 --- /dev/null +++ b/tests/unit/src/com/android/settings/DefaultRingtonePreferenceTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2022 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 com.android.settings; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.ContentResolver; +import android.content.Context; +import android.media.RingtoneManager; +import android.net.Uri; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** Unittest for DefaultRingtonePreference. */ +@RunWith(AndroidJUnit4.class) +public class DefaultRingtonePreferenceTest { + + private DefaultRingtonePreference mDefaultRingtonePreference; + + @Mock + private ContentResolver mContentResolver; + @Mock + private Uri mRingtoneUri; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + Context context = spy(ApplicationProvider.getApplicationContext()); + doReturn(mContentResolver).when(context).getContentResolver(); + + mDefaultRingtonePreference = spy(new DefaultRingtonePreference(context, null /* attrs */)); + doReturn(context).when(mDefaultRingtonePreference).getContext(); + when(mDefaultRingtonePreference.getRingtoneType()) + .thenReturn(RingtoneManager.TYPE_RINGTONE); + mDefaultRingtonePreference.setUserId(1); + } + + @Test + public void onSaveRingtone_nullMimeType_shouldNotSetRingtone() { + when(mContentResolver.getType(mRingtoneUri)).thenReturn(null); + + mDefaultRingtonePreference.onSaveRingtone(mRingtoneUri); + + verify(mDefaultRingtonePreference, never()).setActualDefaultRingtoneUri(mRingtoneUri); + } + + @Test + public void onSaveRingtone_notAudioMimeType_shouldNotSetRingtone() { + when(mContentResolver.getType(mRingtoneUri)).thenReturn("text/plain"); + + mDefaultRingtonePreference.onSaveRingtone(mRingtoneUri); + + verify(mDefaultRingtonePreference, never()).setActualDefaultRingtoneUri(mRingtoneUri); + } +}