Add an info icon to each permission group in location provider permissions

BUG: 182204957

Test: manually tested the UI. Checked intent is sent when the info icon is clicked.

Merged-In: Ia1b8942e13b7c6dcbc2f45549197dbdd1fec9375

Change-Id: Ia1b8942e13b7c6dcbc2f45549197dbdd1fec9375
diff --git a/PermissionController/AndroidManifest.xml b/PermissionController/AndroidManifest.xml
index 80d2db3..91e0cb6 100644
--- a/PermissionController/AndroidManifest.xml
+++ b/PermissionController/AndroidManifest.xml
@@ -47,6 +47,7 @@
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
     <uses-permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED" />
     <uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING" />
+    <uses-permission android:name="android.permission.START_VIEW_PERMISSION_USAGE" />
 
     <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
 
diff --git a/PermissionController/res/layout/image_view_with_divider.xml b/PermissionController/res/layout/image_view_with_divider.xml
new file mode 100644
index 0000000..e1e4332
--- /dev/null
+++ b/PermissionController/res/layout/image_view_with_divider.xml
@@ -0,0 +1,41 @@
+<!--
+  ~ 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.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:id="@+id/widget_frame"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:orientation="horizontal"
+              android:gravity="end|center_vertical">
+
+    <View
+        android:id="@+id/divider"
+        android:layout_width="1dp"
+        android:layout_height="24dp"
+        android:layout_marginLeft="16dp"
+        android:layout_marginRight="16dp"
+        android:layout_gravity="end|center_vertical"
+        android:theme="@style/PreferenceDivider" />
+
+    <ImageButton
+        android:id="@+id/icon"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:layout_gravity="end|center_vertical"
+        android:contentDescription="@string/grant_dialog_button_more_info"
+        android:background="@null" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/PermissionController/res/values/themes.xml b/PermissionController/res/values/themes.xml
index 2a70fde..a4f321b 100644
--- a/PermissionController/res/values/themes.xml
+++ b/PermissionController/res/values/themes.xml
@@ -81,6 +81,8 @@
         <item name="carDividerColor">@*android:color/car_list_divider</item>
     </style>
 
+    <style name="PreferenceDivider" parent="AutoRevokeDivider" />
+
     <style name="AutoRevokeDivider">
         <item name="android:background">@color/divider_color_primary</item>
     </style>
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 9c526d7..7fc4e71 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/AppPermissionGroupsFragment.java
@@ -26,10 +26,14 @@
 
 import android.app.ActionBar;
 import android.app.Activity;
+import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
 import android.icu.text.ListFormatter;
+import android.location.LocationManager;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.UserHandle;
@@ -67,6 +71,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Random;
 
 /**
@@ -282,6 +287,30 @@
                 if (groupInfo.getSubtitle() == PermSubtitle.FOREGROUND_ONLY) {
                     preference.setSummary(R.string.permission_subtitle_only_in_foreground);
                 }
+                // Add an info icon if the package is a location provider
+                LocationManager locationManager = context.getSystemService(LocationManager.class);
+                if (locationManager != null && locationManager.isProviderPackage(mPackageName)) {
+                    Intent sendIntent = new Intent();
+                    sendIntent.setAction(Intent.ACTION_VIEW_PERMISSION_USAGE);
+                    sendIntent.setPackage(mPackageName);
+                    sendIntent.putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, groupName);
+
+                    PackageManager pm = getActivity().getPackageManager();
+                    ActivityInfo activityInfo = sendIntent.resolveActivityInfo(pm, 0);
+                    if (activityInfo != null && Objects.equals(activityInfo.permission,
+                            android.Manifest.permission.START_VIEW_PERMISSION_USAGE)) {
+                        preference.setRightIcon(
+                                context.getDrawable(R.drawable.ic_info_outline),
+                                v -> {
+                                    try {
+                                        startActivity(sendIntent);
+                                    } catch (ActivityNotFoundException e) {
+                                        Log.e(LOG_TAG, "No activity found for viewing permission "
+                                                + "usage.");
+                                    }
+                                });
+                    }
+                }
                 if (groupInfo.isSystem() == mIsSystemPermsScreen) {
                     category.addPreference(preference);
                 } else if (!groupInfo.isSystem()) {
diff --git a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionControlPreference.java b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionControlPreference.java
index fe6ee35..c2aad63 100644
--- a/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionControlPreference.java
+++ b/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/PermissionControlPreference.java
@@ -43,9 +43,9 @@
 import androidx.preference.Preference;
 import androidx.preference.PreferenceViewHolder;
 
+import com.android.permissioncontroller.R;
 import com.android.permissioncontroller.permission.model.AppPermissionGroup;
 import com.android.permissioncontroller.permission.model.AppPermissionUsage.GroupUsage;
-import com.android.permissioncontroller.R;
 import com.android.permissioncontroller.permission.ui.LocationProviderInterceptDialog;
 import com.android.permissioncontroller.permission.utils.LocationUtils;
 
@@ -57,6 +57,7 @@
 public class PermissionControlPreference extends Preference {
     private final @NonNull Context mContext;
     private @Nullable Drawable mWidgetIcon;
+    private @Nullable View.OnClickListener mWidgetIconOnClickListener;
     private @Nullable String mGranted;
     private boolean mUseSmallerIcon;
     private boolean mEllipsizeEnd;
@@ -112,6 +113,20 @@
     }
 
     /**
+     * Sets this preference's right icon with an onClickListener.
+     *
+     * Note that this must be called before preference layout to take effect.
+     *
+     * @param widgetIcon the icon to use.
+     * @param listener the onClickListener attached to the icon.
+     */
+    public void setRightIcon(@NonNull Drawable widgetIcon, @NonNull View.OnClickListener listener) {
+        mWidgetIcon = widgetIcon;
+        setWidgetLayoutResource(R.layout.image_view_with_divider);
+        mWidgetIconOnClickListener = listener;
+    }
+
+    /**
      * Sets this preference's left icon to be smaller than normal.
      *
      * Note that this must be called before preference layout to take effect.
@@ -210,6 +225,9 @@
         if (mWidgetIcon != null) {
             View widgetFrame = holder.findViewById(android.R.id.widget_frame);
             ((ImageView) widgetFrame.findViewById(R.id.icon)).setImageDrawable(mWidgetIcon);
+            if (mWidgetIconOnClickListener != null) {
+                widgetFrame.findViewById(R.id.icon).setOnClickListener(mWidgetIconOnClickListener);
+            }
         }
 
         if (mEllipsizeEnd) {