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

Commit 56cac009 authored by Mao Jinlong's avatar Mao Jinlong Committed by Linux Build Service Account
Browse files

Take persistable uri permission for document provider

ACTION_GET_CONTENT is to simply read/import data.ACTION_OPEN_DOCUMENT
is to have long term, persistent access to documents owned by a
document provider. When user select music as alarm ringtone from
external storage, the music file is possible to be a document provider
file. DeskClock will lose access to document provider file after reboot.
DeskClock need long term, persistent access to documents owned by
document provider. So Take persistable uri permission for document
provider.

Change-Id: I110873d4c49eed34d9cabc8bd457e12eba9ced1f
CRs-Fixed: 1046238
parent 2eabe191
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
@@ -26,10 +26,12 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.Loader;
import android.content.pm.PackageManager;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.DocumentsContract;
import android.provider.Settings;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.LinearLayoutManager;
@@ -52,6 +54,8 @@ import com.android.deskclock.widget.EmptyViewController;
import com.android.deskclock.widget.toast.SnackbarManager;
import com.android.deskclock.widget.toast.ToastManager;

import java.util.List;

/**
 * A fragment that displays a list of alarm time and allows interaction with them.
 */
@@ -382,6 +386,12 @@ public final class AlarmClockFragment extends DeskClockFragment implements
        }
    }

    private List<Alarm> getAlarmsByUri(Context context, Uri uri) {
       final String selection = String.format("%s=?", Alarm.RINGTONE);
       final String[] args = { uri.toString() };
       return Alarm.getAlarms(context.getContentResolver(), selection, args);
    }

    private void updateSelectAlarmRingToneUri(Uri uri) {
        if (uri == null) {
            uri = Alarm.NO_RINGTONE_URI;
@@ -393,6 +403,43 @@ public final class AlarmClockFragment extends DeskClockFragment implements
            LogUtils.e("Could not get selected alarm to set ringtone");
            return;
        }

        // If the selected uri doesn't equals to the original uri, we need
        // to check if the new uir is document uri and take the persistable
        // permission.
        // If there is no other alarm which uses the original uri and it is
        // not the default alarm ringtone uri, then we need to release the
        // permission of the orignal uri.
        if (uri != alarm.alert) {
            Context context = getActivity().getApplicationContext();
            ContentResolver resolver = context.getContentResolver();
            final int takeFlag = Intent.FLAG_GRANT_READ_URI_PERMISSION;

            SharedPreferences sharedPref = Utils.getCESharedPreferences(context);
            String defaultRingTone = sharedPref.getString(
                    DefaultAlarmToneDialog.DEFAULT_RING_TONE_URI_KEY,
                    DefaultAlarmToneDialog.DEFAULT_RING_TONE_DEFAULT);
            Uri defaultUri = Uri.parse(defaultRingTone);

            if (DocumentsContract.isDocumentUri(context, alarm.alert) &&
                    alarm.alert != defaultUri && getAlarmsByUri(context, alarm.alert).size() == 1) {
                try {
                    resolver.releasePersistableUriPermission(alarm.alert, takeFlag);
                } catch (Exception ex) {
                    LogUtils.e("releasePersistableUriPermission exception : "+ ex);
                }
            }

            if (DocumentsContract.isDocumentUri(context, uri)) {
                // Check for the freshest data and take persist permission.
                try {
                    resolver.takePersistableUriPermission(uri, takeFlag);
                } catch (Exception ex) {
                    LogUtils.e("takePersistableUriPermission exception : " + ex);
                }
            }
        }

        alarm.alert = uri;

        // Save the change to alarm.
+3 −1
Original line number Diff line number Diff line
@@ -253,7 +253,9 @@ public final class AlarmTimeClickHandler {
            LogUtils.d(TAG, "Showing ringtone picker.");
            mFragment.startActivityForResult(intent, AlarmClockFragment.REQUEST_CODE_RINGTONE);
        } else {
            final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            // As the minSdkVersion for this app is 19, we don't need to add sdk version check
            // here to use ACTION_OPEN_DOCUMENT.
            final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
            intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, mSelectedAlarm.alert);
            intent.setType(AlarmClockFragment.SEL_AUDIO_SRC);
            mFragment.startActivityForResult(intent, AlarmClockFragment.REQUEST_CODE_EXTERN_AUDIO);
+25 −1
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import com.android.deskclock.data.DataModel;
import com.android.deskclock.provider.Alarm;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.ContentResolver;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -44,6 +45,7 @@ import android.content.DialogInterface.OnClickListener;
import android.media.RingtoneManager;
import android.net.Uri;
import android.preference.DialogPreference;
import android.provider.DocumentsContract;
import android.util.AttributeSet;

public class DefaultAlarmToneDialog extends DialogPreference {
@@ -142,7 +144,9 @@ public class DefaultAlarmToneDialog extends DialogPreference {
            activity.startActivityForResult(intent,
                    AlarmClockFragment.REQUEST_CODE_RINGTONE);
        } else {
            final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            // As the minSdkVersion for this app is 19, we don't need to add sdk version check
            // here to use ACTION_OPEN_DOCUMENT.
            final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
            intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI,
                    oldRingTone);
            intent.setType(AlarmClockFragment.SEL_AUDIO_SRC);
@@ -166,6 +170,26 @@ public class DefaultAlarmToneDialog extends DialogPreference {
        }

        if (uri != oldRingTone) {
            ContentResolver resolver = mContext.getContentResolver();
            final int takeFlags = intent.getFlags() & Intent.FLAG_GRANT_READ_URI_PERMISSION;

            if (DocumentsContract.isDocumentUri(mContext, oldRingTone)) {
                try {
                    resolver.releasePersistableUriPermission(oldRingTone, takeFlags);
                } catch (Exception ex) {
                    LogUtils.e(LogUtils.LOGTAG, "releasePersistableUriPermission exception : "+ ex);
                }
            }

            if (DocumentsContract.isDocumentUri(mContext, uri)) {
                // Check for the freshest data and take persist permission.
                try {
                    resolver.takePersistableUriPermission(uri, takeFlags);
                } catch (Exception ex) {
                    LogUtils.e(LogUtils.LOGTAG, "takePersistableUriPermission exception : "+ ex);
                }
            }

            // sendBroadcast to refresh Alarm's ringtone which is default
            sendRefreshBroadcast(uri);
        }