diff options
author | Jorge Ruesga <jorge@ruesga.com> | 2014-11-12 12:36:00 -0800 |
---|---|---|
committer | Matt Garnes <matt@cyngn.com> | 2014-11-12 12:36:00 -0800 |
commit | 0a17d0168720f00fd19e5ab267b4a26b37260bf8 (patch) | |
tree | 849ccb4f6ef1f29f38531bd19976ad3fa949ebd9 | |
parent | b5563570ec5b28dbf00bac64379cf66cf03462ab (diff) | |
download | android_packages_apps_DeskClock-0a17d0168720f00fd19e5ab267b4a26b37260bf8.tar.gz android_packages_apps_DeskClock-0a17d0168720f00fd19e5ab267b4a26b37260bf8.tar.bz2 android_packages_apps_DeskClock-0a17d0168720f00fd19e5ab267b4a26b37260bf8.zip |
deskclock: take persistent grants of external uris
The new storage api used by the DocumentProvider api only grants temporally the selected uris. This
causes that after a reboot the access to the selected uri is denied. This changes reclaims a persistent
read permission for the selected uri while in use by an alarm.
Change-Id: I3dbdfd1c03ab9d302d559c62ae8311a43ce7b336
Signed-off-by: Jorge Ruesga <jorge@ruesga.com>
-rwxr-xr-x | res/values/cm_strings.xml | 3 | ||||
-rwxr-xr-x | src/com/android/deskclock/AlarmClockFragment.java | 85 |
2 files changed, 87 insertions, 1 deletions
diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml index ce5fc4469..6bff7a3ed 100755 --- a/res/values/cm_strings.xml +++ b/res/values/cm_strings.xml @@ -97,4 +97,7 @@ <!-- Ringtone selection default" --> <string name="ringtone_default">"Default ringtone"</string> + + <!-- Message that describe an error trying to take a persistent grant permission for an uri ringtone --> + <string name="take_persistent_grant_uri_permission_failed_msg">Failed to take persistent grant permission for ringtone</string> </resources> diff --git a/src/com/android/deskclock/AlarmClockFragment.java b/src/com/android/deskclock/AlarmClockFragment.java index 664c52c73..eb88ce072 100755 --- a/src/com/android/deskclock/AlarmClockFragment.java +++ b/src/com/android/deskclock/AlarmClockFragment.java @@ -34,6 +34,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.Loader; +import android.content.UriPermission; import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; @@ -95,6 +96,7 @@ import java.io.File; import java.text.DateFormatSymbols; import java.util.Calendar; import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -556,7 +558,7 @@ public class AlarmClockFragment extends DeskClockFragment implements false); AlarmClockFragment.this.startActivityForResult(intent, REQUEST_CODE_RINGTONE); } else { - final Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, AlarmClockFragment.this.mSelectedAlarm.alert); intent.setType(SEL_AUDIO_SRC); @@ -636,12 +638,69 @@ public class AlarmClockFragment extends DeskClockFragment implements startActivityForResult(intent, REQUEST_CODE_PROFILE); } + private void releaseRingtoneUri(Uri uri) { + final ContentResolver cr = getActivity().getContentResolver(); + if (uri == null || mAdapter == null) { + return; + } + + // Check that the uri is currently persisted + boolean containsUri = false; + for (UriPermission uriPermission : cr.getPersistedUriPermissions()) { + if (uriPermission.getUri().compareTo(uri) == 0) { + containsUri = true; + break; + } + } + if (!containsUri) { + return; + } + + // Check that only one uri is in use + int found = 0; + int count = mAdapter.getCount(); + for (int i = 0; i < count; i++) { + Alarm alarm = new Alarm((Cursor) mAdapter.getItem(i)); + if (alarm.alert != null && uri.compareTo(alarm.alert) == 0) { + found++; + if (found > 1) { + break; + } + } + } + if (found == 1) { + // Release current granted uri + try { + if (uri != null) { + getActivity().getContentResolver().releasePersistableUriPermission( + uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); + } + } catch (SecurityException e) { + // Ignore + } + } + } + private Uri getRingtoneUri(Intent intent) { + // Release the current ringtone uri + releaseRingtoneUri(mSelectedAlarm.alert); + Uri uri; if (mSelectSource == SEL_SRC_RINGTONE) { uri = intent.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI); } else { uri = intent.getData(); + if (uri != null) { + try { + getActivity().getContentResolver().takePersistableUriPermission( + uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); + } catch (SecurityException ex) { + LogUtils.e("Unable to take persistent grant permission for uri " + uri, ex); + uri = null; + final int msgId = R.string.take_persistent_grant_uri_permission_failed_msg; + Toast.makeText(getActivity(), msgId, Toast.LENGTH_SHORT).show(); + } + } } if (uri == null) { uri = Alarm.NO_RINGTONE_URI; @@ -1728,6 +1787,9 @@ public class AlarmClockFragment extends DeskClockFragment implements protected Void doInBackground(Void... parameters) { // Activity may be closed at this point , make sure data is still valid if (context != null && alarm != null) { + // Release the alarm ringtone uri + releaseRingtoneUri(alarm.alert); + ContentResolver cr = context.getContentResolver(); AlarmStateManager.deleteAllInstances(context, alarm.id); Alarm.deleteAlarm(cr, alarm.id); @@ -1746,6 +1808,15 @@ public class AlarmClockFragment extends DeskClockFragment implements final AsyncTask<Void, Void, AlarmInstance> updateTask = new AsyncTask<Void, Void, AlarmInstance>() { @Override + public synchronized void onPreExecute() { + final ListView list = mAlarmsList; + // The alarm list needs to be disabled until the animation finishes to prevent + // possible concurrency issues. It becomes re-enabled after the animations have + // completed. + mAlarmsList.setEnabled(false); + } + + @Override protected AlarmInstance doInBackground(Void... parameters) { if (context != null && alarm != null) { ContentResolver cr = context.getContentResolver(); @@ -1785,6 +1856,18 @@ public class AlarmClockFragment extends DeskClockFragment implements // Dismiss all old instances AlarmStateManager.deleteAllInstances(context, alarm.id); + // Register/Update the ringtone uri + if (alarm.alert != null) { + try { + getActivity().getContentResolver().takePersistableUriPermission( + alarm.alert, Intent.FLAG_GRANT_READ_URI_PERMISSION); + } catch (SecurityException ex) { + // Ignore + } + } + + // Dismiss all old instances + AlarmStateManager.deleteAllInstances(context, alarm.id); // Update alarm Alarm.updateAlarm(cr, alarm); |