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