summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJorge Ruesga <jorge@ruesga.com>2014-11-12 12:36:00 -0800
committerMatt Garnes <matt@cyngn.com>2014-11-12 12:36:00 -0800
commit0a17d0168720f00fd19e5ab267b4a26b37260bf8 (patch)
tree849ccb4f6ef1f29f38531bd19976ad3fa949ebd9
parentb5563570ec5b28dbf00bac64379cf66cf03462ab (diff)
downloadandroid_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-xres/values/cm_strings.xml3
-rwxr-xr-xsrc/com/android/deskclock/AlarmClockFragment.java85
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);