Bug: 22718745 Intents to 'draw over other apps' should go direct to the package's
page instead of the top level one

Settings:
Added two activities to handle app-specific Intent when app invoke permission
management UI.

SettingsActivity:
Added two fragment classes to handle app-specific Intent when app invoke permission
management UI.

AndroidManifest.xml:
We handle both Intent to top level settings and app-specific management UI for
app ops protected permissions.

AppStateAppOpsBridge:
Added a new field to PermissionState to keep track of permission declared vs one
that is actually granted during install time.

AppState{Overlay/Usage/WriteSettings}Bridge:
Updated the fields affected by changes in PermissionState.

{DrawOverlay/UsageAccess/WriteSettings}Details:
Disabled the toggling of permission if the app did not declare for the asked
permission.

Change-Id: Ibf63e4d9a4fbf7899a93d2176abb1204c4f75557
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 1fef233..ce5308a 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2541,6 +2541,18 @@
                 android:value="com.android.settings.applications.ManageApplications" />
         </activity>
 
+        <activity android:name="Settings$AppDrawOverlaySettingsActivity"
+                android:label="@string/draw_overlay_title"
+                android:taskAffinity="">
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.action.MANAGE_OVERLAY_PERMISSION" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="package" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.applications.DrawOverlayDetails" />
+        </activity>
+
         <activity android:name="Settings$WriteSettingsActivity"
                 android:label="@string/write_settings_title"
                 android:taskAffinity="">
@@ -2552,5 +2564,17 @@
                 android:value="com.android.settings.applications.ManageApplications" />
         </activity>
 
+        <activity android:name="Settings$AppWriteSettingsActivity"
+                android:label="@string/write_settings_title"
+                android:taskAffinity="">
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.action.MANAGE_WRITE_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="package" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.applications.WriteSettingsDetails" />
+        </activity>
+
     </application>
 </manifest>
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index f606193..7b94d79 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -116,4 +116,6 @@
     public static class MemorySettingsActivity extends SettingsActivity { /* empty */ }
     public static class OverlaySettingsActivity extends SettingsActivity { /* empty */ }
     public static class WriteSettingsActivity extends SettingsActivity { /* empty */ }
+    public static class AppDrawOverlaySettingsActivity extends SettingsActivity { /* empty */ }
+    public static class AppWriteSettingsActivity extends SettingsActivity { /* empty */ }
 }
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 442ce60..8edec09 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -70,12 +70,14 @@
 import com.android.settings.accessibility.CaptionPropertiesFragment;
 import com.android.settings.accounts.AccountSettings;
 import com.android.settings.accounts.AccountSyncSettings;
+import com.android.settings.applications.DrawOverlayDetails;
 import com.android.settings.applications.InstalledAppDetails;
 import com.android.settings.applications.ManageApplications;
 import com.android.settings.applications.ManageAssist;
 import com.android.settings.applications.ProcessStatsSummary;
 import com.android.settings.applications.ProcessStatsUi;
 import com.android.settings.applications.UsageAccessDetails;
+import com.android.settings.applications.WriteSettingsDetails;
 import com.android.settings.bluetooth.BluetoothSettings;
 import com.android.settings.dashboard.DashboardCategory;
 import com.android.settings.dashboard.DashboardSummary;
@@ -350,6 +352,8 @@
             ProcessStatsUi.class.getName(),
             PowerUsageDetail.class.getName(),
             ProcessStatsSummary.class.getName(),
+            DrawOverlayDetails.class.getName(),
+            WriteSettingsDetails.class.getName(),
     };
 
 
diff --git a/src/com/android/settings/applications/AppStateAppOpsBridge.java b/src/com/android/settings/applications/AppStateAppOpsBridge.java
index 20a00bd..1a69322 100644
--- a/src/com/android/settings/applications/AppStateAppOpsBridge.java
+++ b/src/com/android/settings/applications/AppStateAppOpsBridge.java
@@ -88,10 +88,12 @@
             int[] permissionFlags = permissionState.packageInfo.requestedPermissionsFlags;
             if (requestedPermissions != null) {
                 for (int i = 0; i < requestedPermissions.length; i++) {
-                    if (mPermissions[0].equals(requestedPermissions[i]) &&
-                            (permissionFlags[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0) {
+                    if (mPermissions[0].equals(requestedPermissions[i])) {
                         permissionState.permissionDeclared = true;
-                        break;
+                        if ((permissionFlags[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0) {
+                            permissionState.staticPermissionGranted = true;
+                            break;
+                        }
                     }
                 }
             }
@@ -164,7 +166,7 @@
     }
 
     /*
-     * This method will set the packageInfo and permissionDeclared field of the associated
+     * This method will set the packageInfo and staticPermissionGranted field of the associated
      * PermissionState, which describes a particular package.
      */
     private void loadPermissionsStates(SparseArray<ArrayMap<String, PermissionState>> entries) {
@@ -185,7 +187,7 @@
                     final PermissionState pe = entriesForProfile.get(packageInfo.packageName);
                     if (pe != null) {
                         pe.packageInfo = packageInfo;
-                        pe.permissionDeclared = true;
+                        pe.staticPermissionGranted = true;
                     }
                 }
             }
@@ -279,6 +281,7 @@
         public final String packageName;
         public final UserHandle userHandle;
         public PackageInfo packageInfo;
+        public boolean staticPermissionGranted;
         public boolean permissionDeclared;
         public int appOpMode;
 
@@ -293,7 +296,7 @@
             // permission (this means pre-M gets approval during install time; M apps gets approval
             // during runtime.
             if (appOpMode == AppOpsManager.MODE_DEFAULT) {
-                return permissionDeclared;
+                return staticPermissionGranted;
             }
             return appOpMode == AppOpsManager.MODE_ALLOWED;
         }
diff --git a/src/com/android/settings/applications/AppStateOverlayBridge.java b/src/com/android/settings/applications/AppStateOverlayBridge.java
index 75900a4..c603028 100644
--- a/src/com/android/settings/applications/AppStateOverlayBridge.java
+++ b/src/com/android/settings/applications/AppStateOverlayBridge.java
@@ -66,6 +66,7 @@
             this.packageInfo = permissionState.packageInfo;
             this.appOpMode = permissionState.appOpMode;
             this.permissionDeclared = permissionState.permissionDeclared;
+            this.staticPermissionGranted = permissionState.staticPermissionGranted;
         }
     }
 
diff --git a/src/com/android/settings/applications/AppStateUsageBridge.java b/src/com/android/settings/applications/AppStateUsageBridge.java
index a152901..ef5a2c7 100644
--- a/src/com/android/settings/applications/AppStateUsageBridge.java
+++ b/src/com/android/settings/applications/AppStateUsageBridge.java
@@ -57,6 +57,7 @@
             this.packageInfo = permissionState.packageInfo;
             this.appOpMode = permissionState.appOpMode;
             this.permissionDeclared = permissionState.permissionDeclared;
+            this.staticPermissionGranted = permissionState.staticPermissionGranted;
         }
     }
 
diff --git a/src/com/android/settings/applications/AppStateWriteSettingsBridge.java b/src/com/android/settings/applications/AppStateWriteSettingsBridge.java
index e43b5f5..9dbe13b 100644
--- a/src/com/android/settings/applications/AppStateWriteSettingsBridge.java
+++ b/src/com/android/settings/applications/AppStateWriteSettingsBridge.java
@@ -66,6 +66,7 @@
             this.packageInfo = permissionState.packageInfo;
             this.appOpMode = permissionState.appOpMode;
             this.permissionDeclared = permissionState.permissionDeclared;
+            this.staticPermissionGranted = permissionState.staticPermissionGranted;
         }
     }
 
diff --git a/src/com/android/settings/applications/DrawOverlayDetails.java b/src/com/android/settings/applications/DrawOverlayDetails.java
index 4ea45b1..ef92c21 100644
--- a/src/com/android/settings/applications/DrawOverlayDetails.java
+++ b/src/com/android/settings/applications/DrawOverlayDetails.java
@@ -143,6 +143,8 @@
 
         boolean isAllowed = mOverlayState.isPermissible();
         mSwitchPref.setChecked(isAllowed);
+        // you cannot ask a user to grant you a permission you did not have!
+        mSwitchPref.setEnabled(mOverlayState.permissionDeclared);
         mOverlayPrefs.setEnabled(isAllowed);
         getPreferenceScreen().removePreference(mOverlayPrefs);
 
diff --git a/src/com/android/settings/applications/UsageAccessDetails.java b/src/com/android/settings/applications/UsageAccessDetails.java
index 5317282..7af1d9b 100644
--- a/src/com/android/settings/applications/UsageAccessDetails.java
+++ b/src/com/android/settings/applications/UsageAccessDetails.java
@@ -130,6 +130,7 @@
 
         boolean hasAccess = mUsageState.isPermissible();
         mSwitchPref.setChecked(hasAccess);
+        mSwitchPref.setEnabled(mUsageState.permissionDeclared);
         mUsagePrefs.setEnabled(hasAccess);
 
         ResolveInfo resolveInfo = mPm.resolveActivityAsUser(mSettingsIntent,
diff --git a/src/com/android/settings/applications/WriteSettingsDetails.java b/src/com/android/settings/applications/WriteSettingsDetails.java
index 30533c6..c89e7b3 100644
--- a/src/com/android/settings/applications/WriteSettingsDetails.java
+++ b/src/com/android/settings/applications/WriteSettingsDetails.java
@@ -142,6 +142,8 @@
 
         boolean canWrite = mWriteSettingsState.isPermissible();
         mSwitchPref.setChecked(canWrite);
+        // you can't ask a user for a permission you didn't even declare!
+        mSwitchPref.setEnabled(mWriteSettingsState.permissionDeclared);
         mWriteSettingsPrefs.setEnabled(canWrite);
         getPreferenceScreen().removePreference(mWriteSettingsPrefs);