Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a17d016 authored by Jorge Ruesga's avatar Jorge Ruesga Committed by Matt Garnes
Browse files

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: default avatarJorge Ruesga <jorge@ruesga.com>
parent b5563570
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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>
+84 −1
Original line number Diff line number Diff line
@@ -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);
@@ -1745,6 +1807,15 @@ public class AlarmClockFragment extends DeskClockFragment implements
        final Context context = AlarmClockFragment.this.getActivity().getApplicationContext();
        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) {
@@ -1783,6 +1854,18 @@ public class AlarmClockFragment extends DeskClockFragment implements
                    protected AlarmInstance doInBackground(Void ... parameters) {
                        ContentResolver cr = context.getContentResolver();

                        // 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);