diff options
author | Yorke Lee <yorkelee@google.com> | 2015-07-24 12:27:46 -0700 |
---|---|---|
committer | Yorke Lee <yorkelee@google.com> | 2015-07-24 12:52:02 -0700 |
commit | 5f6c901ad062cd7d88db09b555e28ee354ca66c6 (patch) | |
tree | 204db626234e773f39461181ba0c0b8a3388f428 /src | |
parent | a0018a3f788f381313ee5c5f2b15ddce8d7ec5d1 (diff) |
Protect against lack of WRITE_SYSTEM_SETTINGS AppOp
Guard the following entry points with checks against the AppOp
1) Launch of SoundSettingsFragment
Fallback: Send to system sound settings instead
2) onResume of SoundSettingsFragment (this can happen if the AppOp
is toggled by the user in the background)
Fallback: Return to main Dialer settings instead
3) Toggling of various perferences (this can happen in monkey tests)
Fallback: Show toast, ignore settings chance
Bug: 22660372
Change-Id: Ief5d74166d35a9718ea664f378f6930e777f2923
Diffstat (limited to 'src')
3 files changed, 64 insertions, 9 deletions
diff --git a/src/com/android/dialer/settings/DefaultRingtonePreference.java b/src/com/android/dialer/settings/DefaultRingtonePreference.java index c12e7175a..f2648cb66 100644 --- a/src/com/android/dialer/settings/DefaultRingtonePreference.java +++ b/src/com/android/dialer/settings/DefaultRingtonePreference.java @@ -16,12 +16,17 @@ package com.android.dialer.settings; +import android.app.AppOpsManager; import android.content.Context; import android.content.Intent; import android.media.RingtoneManager; import android.net.Uri; import android.preference.RingtonePreference; import android.util.AttributeSet; +import android.widget.Toast; + +import com.android.contacts.common.util.PermissionsUtil; +import com.android.dialer.R; /** * RingtonePreference which doesn't show default ringtone setting. @@ -44,6 +49,13 @@ public class DefaultRingtonePreference extends RingtonePreference { @Override protected void onSaveRingtone(Uri ringtoneUri) { + if (!PermissionsUtil.hasAppOp(getContext(), AppOpsManager.OPSTR_WRITE_SETTINGS)) { + Toast.makeText( + getContext(), + getContext().getResources().getString(R.string.toast_cannot_write_system_settings), + Toast.LENGTH_SHORT).show(); + return; + } RingtoneManager.setActualDefaultRingtoneUri(getContext(), getRingtoneType(), ringtoneUri); } diff --git a/src/com/android/dialer/settings/DialerSettingsActivity.java b/src/com/android/dialer/settings/DialerSettingsActivity.java index d54053b40..abf854c08 100644 --- a/src/com/android/dialer/settings/DialerSettingsActivity.java +++ b/src/com/android/dialer/settings/DialerSettingsActivity.java @@ -1,23 +1,22 @@ package com.android.dialer.settings; -import com.google.common.collect.Lists; - -import android.content.ComponentName; +import android.app.AppOpsManager; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; -import android.os.UserHandle; +import android.os.Process; import android.os.UserManager; import android.preference.PreferenceActivity; import android.preference.PreferenceManager; -import android.preference.PreferenceActivity.Header; +import android.provider.Settings; import android.telecom.TelecomManager; import android.telephony.TelephonyManager; -import android.text.TextUtils; +import android.util.Log; import android.view.MenuItem; +import android.widget.Toast; -import com.android.dialer.DialtactsActivity; +import com.android.contacts.common.util.PermissionsUtil; import com.android.dialer.R; import java.util.List; @@ -26,8 +25,6 @@ public class DialerSettingsActivity extends PreferenceActivity { protected SharedPreferences mPreferences; - private static final int OWNER_HANDLE_ID = 0; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -44,6 +41,7 @@ public class DialerSettingsActivity extends PreferenceActivity { Header soundSettingsHeader = new Header(); soundSettingsHeader.titleRes = R.string.sounds_and_vibration_title; soundSettingsHeader.fragment = SoundSettingsFragment.class.getName(); + soundSettingsHeader.id = R.id.settings_header_sounds_and_vibration; target.add(soundSettingsHeader); Header quickResponseSettingsHeader = new Header(); @@ -91,6 +89,24 @@ public class DialerSettingsActivity extends PreferenceActivity { } @Override + public void onHeaderClick(Header header, int position) { + if (header.id == R.id.settings_header_sounds_and_vibration) { + // If we don't have the AppOp to write to system settings, go to system sound settings + // instead. Otherwise, perform the super implementation (which launches our own + // preference fragment. + if (!PermissionsUtil.hasAppOp(this, AppOpsManager.OPSTR_WRITE_SETTINGS)) { + Toast.makeText( + this, + getResources().getString(R.string.toast_cannot_write_system_settings), + Toast.LENGTH_SHORT).show(); + startActivity(new Intent(Settings.ACTION_SOUND_SETTINGS)); + return; + } + } + super.onHeaderClick(header, position); + } + + @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { onBackPressed(); diff --git a/src/com/android/dialer/settings/SoundSettingsFragment.java b/src/com/android/dialer/settings/SoundSettingsFragment.java index 7fc9394f8..1dedcaaff 100644 --- a/src/com/android/dialer/settings/SoundSettingsFragment.java +++ b/src/com/android/dialer/settings/SoundSettingsFragment.java @@ -16,7 +16,9 @@ package com.android.dialer.settings; +import android.app.AppOpsManager; import android.content.Context; +import android.content.Intent; import android.media.RingtoneManager; import android.os.Bundle; import android.os.Handler; @@ -30,7 +32,10 @@ import android.preference.PreferenceScreen; import android.provider.Settings; import android.telephony.CarrierConfigManager; import android.telephony.TelephonyManager; +import android.view.MenuItem; +import android.widget.Toast; +import com.android.contacts.common.util.PermissionsUtil; import com.android.dialer.R; import com.android.phone.common.util.SettingsUtil; @@ -127,6 +132,13 @@ public class SoundSettingsFragment extends PreferenceFragment public void onResume() { super.onResume(); + if (!PermissionsUtil.hasAppOp(getContext(), AppOpsManager.OPSTR_WRITE_SETTINGS)) { + // If the user launches this setting fragment, then toggles the WRITE_SYSTEM_SETTINGS + // AppOp, then close the fragment since there is nothing useful to do. + getActivity().onBackPressed(); + return; + } + if (mVibrateWhenRinging != null) { mVibrateWhenRinging.setChecked(shouldVibrateWhenRinging()); } @@ -143,6 +155,14 @@ public class SoundSettingsFragment extends PreferenceFragment */ @Override public boolean onPreferenceChange(Preference preference, Object objValue) { + if (!PermissionsUtil.hasAppOp(getContext(), AppOpsManager.OPSTR_WRITE_SETTINGS)) { + // A user shouldn't be able to get here, but this protects against monkey crashes. + Toast.makeText( + getContext(), + getResources().getString(R.string.toast_cannot_write_system_settings), + Toast.LENGTH_SHORT).show(); + return true; + } if (preference == mVibrateWhenRinging) { boolean doVibrate = (Boolean) objValue; Settings.System.putInt(getActivity().getContentResolver(), @@ -161,6 +181,13 @@ public class SoundSettingsFragment extends PreferenceFragment */ @Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { + if (!PermissionsUtil.hasAppOp(getContext(), AppOpsManager.OPSTR_WRITE_SETTINGS)) { + Toast.makeText( + getContext(), + getResources().getString(R.string.toast_cannot_write_system_settings), + Toast.LENGTH_SHORT).show(); + return true; + } if (preference == mPlayDtmfTone) { Settings.System.putInt(getActivity().getContentResolver(), Settings.System.DTMF_TONE_WHEN_DIALING, |