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

Commit 08703c8b authored by Felipe Leme's avatar Felipe Leme
Browse files

Added option do display and clear URI permissions.

BUG: 26447975
Change-Id: If5269a62908ce37501219ca8dba619041812d800
parent 22b9e6dc
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->

<!-- Style for a preference category without a header title.
     Based on tall_preference_category, but invisible and with some 0dp attributes. -->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+android:id/title"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_marginBottom="0dip"
    android:textAppearance="@android:style/TextAppearance.Material.Body2"
    android:textColor="?android:attr/colorAccent"
    android:paddingBottom="8dp"
    android:paddingTop="16dip"
    android:visible="false" />
+7 −0
Original line number Diff line number Diff line
@@ -3065,6 +3065,13 @@
    <string name="clear_cache_btn_text">Clear cache</string>
    <!-- Manage applications, label that appears next to the cache size -->
    <string name="cache_size_label">Cache</string>
    <!-- Manage applications, individual application info storage screen. Describes the number of URIs (directories or files) an app has been granted access (by another apps)-->
    <plurals name="uri_permissions_text">
        <item quantity="one">1 item</item>
        <item quantity="other">%d items</item>
    </plurals>
    <!-- Manage applications, individual application info storage screen. Button below list of URIs. -->
    <string name="clear_uri_btn_text">Clear access</string>
    <!-- Manage applications, Header name used for other controls -->
    <string name="controls_label">Controls</string>
    <!-- Manage applications, text label for button to kill / force stop an application -->
+12 −0
Original line number Diff line number Diff line
@@ -86,4 +86,16 @@
        android:selectable="false"
        android:layout="@layout/single_button_panel" />

    <com.android.settings.applications.SpacePreference
        android:layout_height="8dp" />

    <PreferenceCategory
        android:key="uri_category"
        android:layout="@layout/headerless_preference_category" >
        <com.android.settings.applications.LayoutPreference
            android:key="clear_uri_button"
            android:layout="@layout/single_button_panel"
            android:selectable="false" />
    </PreferenceCategory>

</PreferenceScreen>
+102 −2
Original line number Diff line number Diff line
@@ -22,9 +22,11 @@ import android.app.AppGlobals;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.UriPermission;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
@@ -37,6 +39,7 @@ import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.text.format.Formatter;
import android.util.Log;
import android.util.MutableInt;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
@@ -49,9 +52,12 @@ import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.Callbacks;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;

public class AppStorageSettings extends AppInfoWithHeader
        implements OnClickListener, Callbacks, DialogInterface.OnClickListener {
@@ -88,6 +94,9 @@ public class AppStorageSettings extends AppInfoWithHeader
    private static final String KEY_CLEAR_DATA = "clear_data_button";
    private static final String KEY_CLEAR_CACHE = "clear_cache_button";

    private static final String KEY_URI_CATEGORY = "uri_category";
    private static final String KEY_CLEAR_URI = "clear_uri_button";

    private Preference mTotalSize;
    private Preference mAppSize;
    private Preference mDataSize;
@@ -102,6 +111,11 @@ public class AppStorageSettings extends AppInfoWithHeader
    private Preference mStorageUsed;
    private Button mChangeStorageButton;

    // Views related to URI permissions
    private Button mClearUriButton;
    private LayoutPreference mClearUri;
    private PreferenceCategory mUri;

    private boolean mCanClearData = true;
    private boolean mHaveSizes = false;

@@ -166,6 +180,13 @@ public class AppStorageSettings extends AppInfoWithHeader
        mClearCacheButton = (Button) ((LayoutPreference) findPreference(KEY_CLEAR_CACHE))
                .findViewById(R.id.button);
        mClearCacheButton.setText(R.string.clear_cache_btn_text);

        // URI permissions section
        mUri = (PreferenceCategory) findPreference(KEY_URI_CATEGORY);
        mClearUri = (LayoutPreference) mUri.findPreference(KEY_CLEAR_URI);
        mClearUriButton = (Button) mClearUri.findViewById(R.id.button);
        mClearUriButton.setText(R.string.clear_uri_btn_text);
        mClearUriButton.setOnClickListener(this);
    }

    @Override
@@ -189,6 +210,8 @@ public class AppStorageSettings extends AppInfoWithHeader
            }
        } else if (v == mChangeStorageButton && mDialogBuilder != null && !isMoveInProgress()) {
            mDialogBuilder.show();
        } else if (v == mClearUriButton) {
            clearUriPermissions();
        }
    }

@@ -239,7 +262,6 @@ public class AppStorageSettings extends AppInfoWithHeader
            }
            mClearDataButton.setEnabled(false);
            mClearCacheButton.setEnabled(false);

        } else {
            mHaveSizes = true;
            long codeSize = mAppEntry.codeSize;
@@ -301,6 +323,7 @@ public class AppStorageSettings extends AppInfoWithHeader
            return false;
        }
        refreshSizeInfo();
        refreshGrantedUriPermissions();

        final VolumeInfo currentVol = getActivity().getPackageManager()
                .getPackageCurrentVolume(mAppEntry.info);
@@ -413,6 +436,83 @@ public class AppStorageSettings extends AppInfoWithHeader
        }
    }

    private void refreshGrantedUriPermissions() {
        // Clear UI first (in case the activity has been resumed)
        removeUriPermissionsFromUi();

        // Gets all URI permissions from am.
        ActivityManager am = (ActivityManager) getActivity().getSystemService(
                Context.ACTIVITY_SERVICE);
        List<UriPermission> perms =
                am.getGrantedUriPermissions(mAppEntry.info.packageName).getList();

        if (perms.isEmpty()) {
            mClearUriButton.setVisibility(View.GONE);
            return;
        }

        PackageManager pm = getActivity().getPackageManager();

        // Group number of URIs by app.
        Map<CharSequence, MutableInt> uriCounters = new TreeMap<>();
        for (UriPermission perm : perms) {
            String authority = perm.getUri().getAuthority();
            ProviderInfo provider = pm.resolveContentProvider(authority, 0);
            CharSequence app = provider.applicationInfo.loadLabel(pm);
            MutableInt count = uriCounters.get(app);
            if (count == null) {
                uriCounters.put(app, new MutableInt(1));
            } else {
                count.value++;
            }
        }

        // Dynamically add the preferences, one per app.
        int order = 0;
        for (Map.Entry<CharSequence, MutableInt> entry : uriCounters.entrySet()) {
            int numberResources = entry.getValue().value;
            Preference pref = new Preference(getPrefContext());
            pref.setTitle(entry.getKey());
            pref.setSummary(getPrefContext().getResources()
                    .getQuantityString(R.plurals.uri_permissions_text, numberResources,
                            numberResources));
            pref.setSelectable(false);
            pref.setLayoutResource(R.layout.horizontal_preference);
            pref.setOrder(order);
            Log.v(TAG, "Adding preference '" + pref + "' at order " + order);
            mUri.addPreference(pref);
        }

        if (mAppControlRestricted) {
            mClearUriButton.setEnabled(false);
        }

        mClearUri.setOrder(order);
        mClearUriButton.setVisibility(View.VISIBLE);

    }

    private void clearUriPermissions() {
        // Synchronously revoke the permissions.
        final ActivityManager am = (ActivityManager) getActivity().getSystemService(
                Context.ACTIVITY_SERVICE);
        am.clearGrantedUriPermissions(mAppEntry.info.packageName);

        // Update UI
        refreshGrantedUriPermissions();
    }

    private void removeUriPermissionsFromUi() {
        // Remove all preferences but the clear button.
        int count = mUri.getPreferenceCount();
        for (int i = count - 1; i >= 0; i--) {
            Preference pref = mUri.getPreference(i);
            if (pref != mClearUri) {
                mUri.removePreference(pref);
            }
        }
    }

    @Override
    protected AlertDialog createDialog(int id, int errorCode) {
        switch (id) {