Merge "Create button which ignores clicks when window is partially obscured"
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/data/UnusedPackagesLiveData.kt b/PermissionController/src/com/android/permissioncontroller/permission/data/UnusedPackagesLiveData.kt
index 85cbbf9..b97c275 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/data/UnusedPackagesLiveData.kt
+++ b/PermissionController/src/com/android/permissioncontroller/permission/data/UnusedPackagesLiveData.kt
@@ -17,11 +17,15 @@
 package com.android.permissioncontroller.permission.data
 
 import android.os.UserHandle
+import android.provider.DeviceConfig
+import android.provider.DeviceConfig.NAMESPACE_PERMISSIONS
 import android.util.ArraySet
 import android.util.Log
+import com.android.permissioncontroller.PermissionControllerApplication
 import com.android.permissioncontroller.hibernation.getUnusedThresholdMs
 import com.android.permissioncontroller.hibernation.isHibernationEnabled
 import com.android.permissioncontroller.hibernation.lastTimePackageUsed
+import com.android.permissioncontroller.permission.utils.Utils
 
 /**
  * Gets all unused packages from an existing live data that have not been opened in a few months
@@ -37,8 +41,8 @@
 
     private val LOG_TAG = UnusedPackagesLiveData::class.java.simpleName
 
-    private val unusedThreshold = getUnusedThresholdMs()
-    private val usageStatsLiveData = UsageStatsLiveData[unusedThreshold]
+    private var unusedThreshold = getUnusedThresholdMs()
+    private var usageStatsLiveData = UsageStatsLiveData[unusedThreshold]
 
     init {
         addSource(usageStatsLiveData) {
@@ -50,6 +54,22 @@
         addSource(sourceLiveData) {
             update()
         }
+        DeviceConfig.addOnPropertiesChangedListener(
+            NAMESPACE_PERMISSIONS,
+            PermissionControllerApplication.get().mainExecutor,
+            { properties ->
+                for (key in properties.keyset) {
+                    if (key == Utils.PROPERTY_HIBERNATION_UNUSED_THRESHOLD_MILLIS) {
+                        removeSource(usageStatsLiveData)
+                        unusedThreshold = getUnusedThresholdMs()
+                        usageStatsLiveData = UsageStatsLiveData[unusedThreshold]
+                        addSource(usageStatsLiveData) {
+                            update()
+                        }
+                    }
+                }
+            }
+        )
     }
 
     override fun onUpdate() {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/debug/ExpandablePreferenceGroup.java b/PermissionController/src/com/android/permissioncontroller/permission/debug/ExpandablePreferenceGroup.java
deleted file mode 100644
index 676a63c..0000000
--- a/PermissionController/src/com/android/permissioncontroller/permission/debug/ExpandablePreferenceGroup.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-package com.android.permissioncontroller.permission.debug;
-
-import android.content.Context;
-import android.text.TextUtils;
-import android.util.Pair;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import androidx.annotation.DrawableRes;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceGroup;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.permissioncontroller.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A preference group that expands/collapses its children when clicked.
- */
-public class ExpandablePreferenceGroup extends PreferenceGroup {
-    private @NonNull Context mContext;
-    private @NonNull List<Preference> mPreferences;
-    private @NonNull List<Pair<Integer, CharSequence>> mSummaryIcons;
-    private boolean mExpanded;
-
-    public ExpandablePreferenceGroup(@NonNull Context context) {
-        super(context, null);
-
-        mContext = context;
-        mPreferences = new ArrayList<>();
-        mSummaryIcons = new ArrayList<>();
-        mExpanded = false;
-
-        setLayoutResource(R.layout.preference_usage);
-        setWidgetLayoutResource(R.layout.image_view);
-        setOnPreferenceClickListener(preference -> {
-            if (!mExpanded) {
-                int numPreferences = mPreferences.size();
-                for (int i = 0; i < numPreferences; i++) {
-                    super.addPreference(mPreferences.get(i));
-                }
-            } else {
-                removeAll();
-            }
-            mExpanded = !mExpanded;
-            return true;
-        });
-    }
-
-    @Override
-    public void onBindViewHolder(PreferenceViewHolder holder) {
-        ImageView icon = (ImageView) holder.findViewById(android.R.id.icon);
-        int rightIconSize = mContext.getResources().getDimensionPixelSize(
-                R.dimen.secondary_app_icon_size);
-        icon.setMaxWidth(rightIconSize);
-        icon.setMaxHeight(rightIconSize);
-
-        super.onBindViewHolder(holder);
-
-        TextView summary = (TextView) holder.findViewById(android.R.id.summary);
-        summary.setMaxLines(1);
-        summary.setEllipsize(TextUtils.TruncateAt.END);
-
-        ImageView rightImageView = holder.findViewById(
-                android.R.id.widget_frame).findViewById(R.id.icon);
-        if (mExpanded) {
-            rightImageView.setImageResource(R.drawable.ic_arrow_up);
-        } else {
-            rightImageView.setImageResource(R.drawable.ic_arrow_down);
-        }
-
-        holder.setDividerAllowedAbove(false);
-        holder.setDividerAllowedBelow(false);
-
-        holder.findViewById(R.id.title_widget_frame).setVisibility(View.GONE);
-
-        ViewGroup summaryFrame = (ViewGroup) holder.findViewById(R.id.summary_widget_frame);
-        if (mSummaryIcons.isEmpty()) {
-            summaryFrame.setVisibility(View.GONE);
-        } else {
-            summaryFrame.removeAllViews();
-            int numIcons = mSummaryIcons.size();
-            for (int i = 0; i < numIcons; i++) {
-                LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class);
-                ViewGroup group = (ViewGroup) inflater.inflate(R.layout.title_summary_image_view,
-                        null);
-                ImageView imageView = group.requireViewById(R.id.icon);
-                Pair<Integer, CharSequence> summaryIcons = mSummaryIcons.get(i);
-                imageView.setImageResource(summaryIcons.first);
-                if (summaryIcons.second != null) {
-                    imageView.setContentDescription(summaryIcons.second);
-                }
-                summaryFrame.addView(group);
-            }
-        }
-    }
-
-    @Override
-    public boolean addPreference(Preference preference) {
-        mPreferences.add(preference);
-        return true;
-    }
-
-    /**
-     * Show the given icon next to this preference's summary.
-     *
-     * @param resId the resourceId of the drawable to use as the icon.
-     */
-    public void addSummaryIcon(@DrawableRes int resId, @Nullable CharSequence contentDescription) {
-        mSummaryIcons.add(Pair.create(resId, contentDescription));
-    }
-}
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
index 6807082..f3a8454 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
@@ -531,7 +531,8 @@
         autoRevokeSwitch.setKey(AUTO_REVOKE_SWITCH_KEY);
         autoRevokeCategory.addPreference(autoRevokeSwitch);
 
-        FooterPreference autoRevokeSummary = new FooterPreference(context);
+        Preference autoRevokeSummary = SdkLevel.isAtLeastS() ? new FooterPreference(context)
+                : new Preference(context);
         autoRevokeSummary.setIcon(Utils.applyTint(getActivity(), R.drawable.ic_info_outline,
                 android.R.attr.colorControlNormal));
         autoRevokeSummary.setKey(AUTO_REVOKE_SUMMARY_KEY);
@@ -548,7 +549,7 @@
                 .findPreference(AUTO_REVOKE_CATEGORY_KEY);
         SwitchPreference autoRevokeSwitch = autoRevokeCategory.findPreference(
                 AUTO_REVOKE_SWITCH_KEY);
-        FooterPreference autoRevokeSummary = autoRevokeCategory.findPreference(
+        Preference autoRevokeSummary = autoRevokeCategory.findPreference(
                 AUTO_REVOKE_SUMMARY_KEY);
 
         if (!state.isEnabledGlobal()) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/ManageStandardPermissionsFragment.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/ManageStandardPermissionsFragment.java
index 2333d12..f7959cd 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/ManageStandardPermissionsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/ManageStandardPermissionsFragment.java
@@ -25,14 +25,10 @@
 import android.app.Application;
 import android.content.Intent;
 import android.os.Bundle;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-import android.text.style.ClickableSpan;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
-import android.view.View;
 
 import androidx.lifecycle.ViewModelProvider;
 import androidx.preference.Preference;
@@ -170,7 +166,12 @@
         Preference autoRevokePreference = screen.findPreference(AUTO_REVOKE_KEY);
         if (numAutoRevoked != null && numAutoRevoked != 0) {
             if (autoRevokePreference == null) {
-                autoRevokePreference = createAutoRevokeFooterPreference();
+                if (SdkLevel.isAtLeastS()) {
+                    autoRevokePreference = createAutoRevokeFooterPreferenceForSPlus();
+                } else {
+                    autoRevokePreference = createAutoRevokeFooterPreferenceForR();
+                }
+                autoRevokePreference.setKey(AUTO_REVOKE_KEY);
                 screen.addPreference(autoRevokePreference);
             }
         } else if (numAutoRevoked != null && autoRevokePreference != null) {
@@ -180,51 +181,29 @@
         return screen;
     }
 
-    private Preference createAutoRevokeFooterPreference() {
-        Preference autoRevokePreference;
-        if (SdkLevel.isAtLeastS()) {
-            FooterPreference.Builder autoRevokePreferenceBuilder =
-                    new FooterPreference.Builder(getContext());
-            autoRevokePreferenceBuilder.setKey(AUTO_REVOKE_KEY);
-            // Description contains a "Learn more" link
-            CharSequence descriptionText = getContext().getText(
-                    R.string.auto_revoked_apps_page_summary);
-            SpannableStringBuilder sb = new SpannableStringBuilder();
-            sb.append(descriptionText);
-            sb.append("\n\n");
-            CharSequence learnMoreText = getContext().getText(
-                    R.string.permission_usage_access_dialog_learn_more);
-            ClickableSpan link = new ClickableSpan() {
-                @Override
-                public void onClick(View view) {
-                    mViewModel.showAutoRevoke(ManageStandardPermissionsFragment.this,
-                            UnusedAppsFragment.createArgs(
-                                    getArguments().getLong(EXTRA_SESSION_ID,
-                                            INVALID_SESSION_ID)));
-
-                }
-            };
-            sb.append(learnMoreText, link, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
-            autoRevokePreferenceBuilder.setTitle(sb);
-            autoRevokePreference = autoRevokePreferenceBuilder.build();
-            autoRevokePreference.setIcon(R.drawable.ic_info_outline_accent);
-        } else {
-            autoRevokePreference = new FixedSizeIconPreference(
-                    getPreferenceManager().getContext(), true, true);
-            autoRevokePreference.setOrder(-1);
-            autoRevokePreference.setKey(AUTO_REVOKE_KEY);
-            autoRevokePreference.setSingleLineTitle(false);
-            autoRevokePreference.setIcon(R.drawable.ic_info_outline_accent);
-            autoRevokePreference.setTitle(
-                    R.string.auto_revoke_permission_notification_title);
-            autoRevokePreference.setSummary(
-                    R.string.auto_revoke_setting_subtitle);
-            autoRevokePreference.setOnPreferenceClickListener(preference -> {
-                mViewModel.showAutoRevoke(this, UnusedAppsFragment.createArgs(
-                        getArguments().getLong(EXTRA_SESSION_ID, INVALID_SESSION_ID)));
-                return true;
+    private FooterPreference createAutoRevokeFooterPreferenceForSPlus() {
+        FooterPreference autoRevokePreference = new FooterPreference(getContext());
+        autoRevokePreference.setSummary(R.string.auto_revoked_apps_page_summary);
+        autoRevokePreference.setLearnMoreAction(view -> {
+            mViewModel.showAutoRevoke(this, UnusedAppsFragment.createArgs(
+                            getArguments().getLong(EXTRA_SESSION_ID, INVALID_SESSION_ID)));
             });
-        }
+        return autoRevokePreference;
+    }
+
+    private Preference createAutoRevokeFooterPreferenceForR() {
+        Preference autoRevokePreference = new FixedSizeIconPreference(
+                getPreferenceManager().getContext(), true, true);
+        autoRevokePreference.setOrder(-1);
+        autoRevokePreference.setSingleLineTitle(false);
+        autoRevokePreference.setIcon(R.drawable.ic_info_outline_accent);
+        autoRevokePreference.setTitle(R.string.auto_revoke_permission_notification_title);
+        autoRevokePreference.setSummary(R.string.auto_revoke_setting_subtitle);
+        autoRevokePreference.setOnPreferenceClickListener(preference -> {
+            mViewModel.showAutoRevoke(this, UnusedAppsFragment.createArgs(
+                    getArguments().getLong(EXTRA_SESSION_ID, INVALID_SESSION_ID)));
+            return true;
+        });
         return autoRevokePreference;
     }
 
diff --git a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/debug/PermissionUsageFragmentTest.kt b/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/debug/PermissionUsageFragmentTest.kt
deleted file mode 100644
index bbca40b..0000000
--- a/PermissionController/tests/inprocess/src/com/android/permissioncontroller/permission/debug/PermissionUsageFragmentTest.kt
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-
-package com.android.permissioncontroller.permission.debug
-
-import android.Manifest.permission.CAMERA
-import android.content.Intent
-import android.permission.cts.PermissionUtils.grantPermission
-import android.permission.cts.PermissionUtils.install
-import android.permission.cts.PermissionUtils.uninstallApp
-import androidx.test.espresso.Espresso.onView
-import androidx.test.espresso.action.ViewActions.click
-import androidx.test.espresso.matcher.ViewMatchers.withContentDescription
-import androidx.test.espresso.matcher.ViewMatchers.withText
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.rule.ActivityTestRule
-import com.android.compatibility.common.util.SystemUtil.eventually
-import com.android.permissioncontroller.R
-import com.android.permissioncontroller.getPreferenceSummary
-import com.android.permissioncontroller.permission.PermissionHub2Test
-import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity
-import com.android.permissioncontroller.scrollToPreference
-import com.google.common.truth.Truth.assertThat
-import org.junit.After
-import org.junit.Ignore
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/**
- * Simple tests for {@link PermissionUsageFragment}
- */
-@RunWith(AndroidJUnit4::class)
-class PermissionUsageFragmentTest : PermissionHub2Test() {
-    private val APK =
-            "/data/local/tmp/permissioncontroller/tests/inprocess/AppThatUsesCameraPermission.apk"
-    private val APP = "com.android.permissioncontroller.tests.appthatrequestpermission"
-    private val APP_LABEL = "CameraRequestApp"
-
-    @get:Rule
-    val managePermissionsActivity = object : ActivityTestRule<ManagePermissionsActivity>(
-            ManagePermissionsActivity::class.java) {
-        override fun getActivityIntent() = Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE)
-
-        override fun beforeActivityLaunched() {
-            install(APK)
-            grantPermission(APP, CAMERA)
-
-            accessCamera()
-        }
-    }
-
-    @Ignore("ACTION_REVIEW_PERMISSION_USAGE is handled by the new UI and will need a new test")
-    @Test
-    fun cameraAccessShouldBeShown() {
-        eventually {
-            try {
-                scrollToPreference(APP_LABEL)
-            } catch (e: Exception) {
-                onView(withContentDescription(R.string.permission_usage_refresh)).perform(click())
-                throw e
-            }
-        }
-
-        assertThat(getPreferenceSummary(APP_LABEL)).isEqualTo("Camera")
-
-        // Expand usage
-        onView(withText(APP_LABEL)).perform(click())
-    }
-
-    @After
-    fun uninstallTestApp() {
-        uninstallApp(APP)
-    }
-}
\ No newline at end of file