Commit 7c1dd11f authored by Sam Mortimer's avatar Sam Mortimer Committed by Arne Coucheron

[2/2] Settings: Privacy Guard

 * This has been partially split into CMParts. The
   AppOps functionality still lives here.

Pulled together mostly (if not all) from:

Author: Steve Kondik <shade@chemlab.org>
Date:   Tue Feb 25 14:02:16 2014 +0100
settings: Relocate Privacy Guard icons to framework
* So we can use them in the permission dialog for MODE_ASK
Change-Id: Ia9bac7dff0bbe91ae48db5d4b0d8f46feb9fdf86

Author: DvTonder <david.vantonder@gmail.com>
Date:   Thu Jan 16 19:01:23 2014 -0500
Settings: Fix up top level "Privacy" section
Change-Id: Id4dbda10a891c793bc6eb3c42807cc0e3f6092cc

Author: Danny Baumann <dannybaumann@web.de>
Date:   Fri Nov 8 13:37:07 2013 +0100
Add back privacy guard manager.
Change-Id: Ic9fbbae137bb8425fe72a6cdb2f17117351b5709

Author: Chirayu Desai <cdesai@cyanogenmod.org>
Date:   Sat Dec 28 18:51:46 2013 +0530
PrivacyGuard: Specify a default value in Settings.getInt method call
* While privacy guard is enabled by default, the default value specified
  here is returned only when the setting is not defined or not an integer.
Change-Id: Iaedffcc76a23a310aa7915f6a42ccce83ba5d2a6

Author: Matt Mower <mowerm@gmail.com>
Date:   Wed Feb 5 19:40:37 2014 -0600
PrivacyGuard: confirm permissions reset
The button to reset all application permissions to enabled looks
suspiciously like a refresh button. Prompt the user with a confirmation
dialog to make sure they know what they've pressed.
Change-Id: I0444c5bf8e9533feccf890055d34d3200609c6f6

Change-Id: I2e10cb4d395e2e7e5141d2fadada9e9b21cd7fbf

su: Add Root access app-ops control

Adds an app-ops option for root access.

Platform-signed apps weren't previously being listed but there are some
that use root access (FileManager comes to mind).

So we list all of them, but for platform-signed apps we only show the
root toggle and none of the permission-based ones.

Change-Id: Ie716974156d55eb66061e78dc39505569e5bdc2a

AppOps: Add more operations in app ops settings.

Add following operations in app ops settings.

-- Wifi enable/disable
-- Bluetooth enable/disable

Change-Id: I32183d77b88c326168557444a445765b5a69de6f

AppOps: Add support for nfc operation

Add support for nfc operation

Change-Id: I0ca617b11d3f65f80cc49c3f629312e2fee1ba91

AppOps: Add mobile data-on permission control.

Add mobile data-on permission control.

Change-Id: I0956fb1575addb5f4e522e664a80442120190b86

Settings: Convert AppOps array items to string references

* Avoid future breakage
 This will need conversion of all AOSP translated arrays to strings

Change-Id: I2e52e4013d1232d529ce5b9e3aae3502c42e938a

AppOps: Add 'Always ask' option under appOps setting.

Add always ask option for each operation.

Change-Id: Ia4f331a5b7d0b1c8ae6946c55a4f78818fe0454f

AppOps: Use switch widget for non-strict ops.

There are few Ops for which 'Always Ask' mode is not allwoed.
So use switch widget to control such Ops.

Change-Id: Ic7464a207c00e4cb9efff57c1f060e04379c1ee7

Allow disabling the privacy guard notification - port from cm-12.1 (1/3)

Change-Id: Iebf4545c1a65b10036a4865bae29d14e86b12d07

Fix advanced privacy guard screen

Change-Id: I1064f2df748b21384f53219b87645f1569f595d5
Signed-off-by: default avatarRoman Birg <roman@cyngn.com>

[1/2] Settings AppOps: show/hide app type and allow/deny counters

Squash of:

Author: Sam Mortimer <sam@mortimer.me.uk>
Date:   Thu Oct 3 13:51:31 2013 -0700
AppOps: menu options to show/hide user and system apps
Change-Id: Ia55364c361db949a891e4b53a757ee4dff519eb6

Author: Sam Mortimer <sam@mortimer.me.uk>
Author: Danny Baumann <dannybaumann@web.de>
Date:   Wed Oct 2 22:24:14 2013 -0700
[1/2] AppOps: Show allowed/ignored counts
Change-Id: Ia27737155c33e934df9a2a1fcff88379240fd096

Author: Sam Mortimer <sam@mortimer.me.uk>
Date:   Sun Dec 1 21:39:07 2013 -0800
AppOps: only apply app type filters to summary screen
    *) If buildState() is called for a single package, do
       not apply hide user/system app filters.
    *) Fixes show detail display when called via
       long press in privacyguard and an AppOp hide
       filter is ticked.
Change-Id: If31d094fb989836ab6829daeefe820695032c0ed

Change-Id: I4d6f37b3923eb9bc98d67101d6f0ef481a427682

privacyguard: Add Superuser summary

Adds superuser summary to the privacy guard "Advanced" menu, this
is useful for auditing purposes. The tab is only visible when root
for apps is enabled.

Change-Id: I0b71c51d10e44e69102c311e526cdb1fde9bda26

pg

Change-Id: I4e9630a0bf606e863e191e24ce448bbeb5ee7ebb

Settings : Fix default privacy guard preference

Ensure we write to the correct table.
CYNGNOS-2264

Change-Id: I1260cf665080631e3e2ec19b371a79eee273c6d2

Launch app privacy settings when tapping on PG notification (2/2)

Based on https://github.com/SlimRoms/packages_apps_Settings/commit/46bb1442aa96aad6890e3ce7b6f3c0466ababf25

JIRA: CYAN-6077
Change-Id: I8632e8c944c1d5d7ad2fb2a2276bae5fe2d4a0a0

Update privacy guard reset icon

Change-Id: Ia636b08fea0d21c0185d053ecf601d1ddcf5a828

Pick missing patch from cm12.1 for missing privacy icon

40304370
Author: jrizzoli <joey@cyanogenmoditalia.it>
Date:   Fri Apr 24 15:00:28 2015 +0200
Settings: update dashboard icons

1a1820d2
Author: blunden <blunden2@gmail.com>
Date:   Sat Dec 6 20:18:20 2014 +0100
Update the Privacy category drawable

Change-Id: I587622df9a75d69405b17d60f0e8b0046ecf94f6

PrivacyGuard: Tint the enabled icon

The enabled icon was white and when enabled, the icon would get
the exact same color as the background, rendering impossible to see.

Change-Id: I4dc2b52cfca46abf2eff28a0b25918d42cf39f09

Check boxes to Switches in PrivacyGuardPerfs

Change-Id: I329df30a6a095a6a5f5829d8b627b00769e18685

appops: Load the app list asynchronously

The AppList is pretty big and it is loading in the UI thread. This
is noticeable even on high-end chips and there is a definite possibility
that it throws an ANR on lower-end ones.

This patchset adds an asynchronous loader and updates the privacy guard
to use it.

Change-Id: I81f3fb64604af07a351f8cbdfffa7454389e2cee

Settings: Fix off-by-one SectionIndexer in PrivacyGuard.

Change-Id: If97876214d6f532ca4e5a09f09d881cd4fbf0231

Settings: Fix inflate exception on search. Dynamically replace nested fragment.

   When PrivacyGuard is opened, the parent fragment would inflate the layout
   which contained a nested fragment. This is bad behavior. Since we couldn't
   keep track of the fragments lifecycle, the fragment we instantiated during
   inflation would cause an inflate exception if and when we toggled the search
   view within the current context.

   Mitigate the crash by programmatically replacing the fragment after instantiating it once.

   AndroidRuntime
          E  FATAL EXCEPTION: main
          E  Process: com.android.settings, PID: 12372
          E  android.view.InflateException: Binary XML file line #21: Error inflating class fragment
          E      at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:763)
          E      at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
          E      at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
           ...
          E  Caused by: java.lang.IllegalArgumentException: Binary XML file line #21: Duplicate id 0x7f1001a2, tag nul
             l, or parent id 0xffffffff with another fragment for com.android.settings.privacyguard.PrivacyGuardPrefs
          E      at android.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2120)
          E      at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:177)
          E      at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:733)
          E      ... 25 more

Change-Id: I6820ad7d35814f150eedf91140e21c0b8e23322b

settings: Use consistent headers for Privacy Guard

 * Show "Privacy Guard" instead of "App ops" in advanced settings

Change-Id: I98107ba3ad94ba22bbd4dc9e92ea97a36f664ab8

Do not allow privacy guard for core system apps.

Hide any applications that have the system UID as well as System UI from
privacy guard. Enabling this on these core apps can have disastrous
consequences, since many privacy guard authorization requests will queue
up. This can cause the system process or System UI to be killed when
they ANR while they wait at the end of a very long queue for the user to authorize them.

By using privacy guard, you are trusting that the system will control
and protect these permissions in the first place; there is no need to protect
the system from itself.

Change-Id: I478d6a6783a4c06fa7ad01a96c413290b232636c

PrivacyGuard: restore ListView position on resume, for real

ListView gets reloaded each time the activity is resumed,
so we have to restore the position after LoadManager finishes its job

Change-Id: I8f05027aaf8ef85481ecb578efa2c2d2c6c6256d

Settings: persist privacy guard dialogs across rotates

Ref: CYNGNOS-933

Change-Id: I778ff0152dd4a1c0152dca68e82cc89a41f88508
Signed-off-by: default avatarRoman Birg <roman@cyngn.com>
parent 538a3370
......@@ -1385,11 +1385,10 @@
</intent-filter>
</activity>
<!--
<activity android:name="Settings$AppOpsSummaryActivity"
android:label="@string/app_ops_settings"
android:label="@*cyanogenmod.platform:string/privacy_guard_manager_title"
android:taskAffinity=""
android:enabled="false">
android:excludeFromRecents="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.settings.APP_OPS_SETTINGS" />
......@@ -1400,7 +1399,6 @@
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.applications.AppOpsSummary" />
</activity>
-->
<activity android:name="Settings$BackgroundCheckSummaryActivity"
android:label="@string/background_check_title"
......@@ -1435,6 +1433,30 @@
android:value="true" />
</activity>
<!-- Still need a top-level activity for showing app ops details. Aliasing
trick is so the code that is now a fragment can still be called
AppOpsDetails. -->
<activity android:name=".applications.AppOpsDetailsTop"
android:label="@*cyanogenmod.platform:string/privacy_guard_manager_title"
android:exported="true"
android:taskAffinity=""
android:excludeFromRecents="true"
android:parentActivityName="Settings$AppOpsSummaryActivity">
</activity>
<!-- Keep compatibility with old shortcuts. -->
<activity-alias android:name=".applications.AppOpsDetails"
android:label="@*cyanogenmod.platform:string/privacy_guard_manager_title"
android:exported="true"
android:excludeFromRecents="true"
android:targetActivity=".applications.AppOpsDetailsTop">
<intent-filter>
<action android:name="android.settings.APP_OPS_DETAILS_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="package" />
</intent-filter>
</activity-alias>
<activity android:name="Settings$LocationSettingsActivity"
android:label="@string/location_settings_title"
android:icon="@drawable/ic_settings_location"
......
......@@ -22,6 +22,8 @@
-keep class com.android.settings.display.*FragmentForSetupWizard
-keep class com.android.settings.display.NightDisplaySettings
-keep class com.android.settings.cyanogenmod.*Settings
# Keep click responders
-keepclassmembers class com.android.settings.inputmethod.UserDictionaryAddWordActivity {
*** onClick*(...);
......
......@@ -42,6 +42,7 @@
android:id="@+id/op_name"
android:layout_column="1"
android:layout_row="0"
android:layout_columnSpan="2"
android:layout_gravity="fill_horizontal"
android:layout_marginTop="2dip"
android:singleLine="true"
......@@ -53,20 +54,47 @@
android:id="@+id/op_time"
android:layout_column="1"
android:layout_row="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="fill_horizontal|top"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textAlignment="viewStart" />
<TextView
android:id="@+id/op_counts"
android:layout_column="1"
android:layout_row="2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="fill_horizontal|top"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textAlignment="viewStart" />
<Switch android:id="@+id/switchWidget"
<Spinner
android:id="@+id/spinnerWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dip"
android:layout_column="2"
android:layout_row="0"
android:layout_rowSpan="2"
android:layout_rowSpan="3"
android:padding="8dip"
android:focusable="false"
android:entries="@+array/app_ops_permissions" />
<Switch
android:id="@+id/switchWidget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dip"
android:layout_column="2"
android:layout_row="0"
android:layout_rowSpan="3"
android:padding="8dip"
android:focusable="false"
android:clickable="true" />
</GridLayout>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2013 The CyanogenMod 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.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/show_user_apps"
android:title="@string/app_ops_show_user_apps"
android:checkable="true" />
<item android:id="@+id/show_system_apps"
android:title="@string/app_ops_show_system_apps"
android:checkable="true" />
<item android:id="@+id/reset_counters"
android:title="@string/app_ops_reset_counters" />
</menu>
......@@ -615,25 +615,11 @@
<item>monitor high power location</item>
<item>get usage stats</item>
<item>mute/unmute microphone</item>
<item>show toast</item>
<item>project media</item>
<item>activate VPN</item>
<item>write wallpaper</item>
<item>assist structure</item>
<item>assist screenshot</item>
<item>read phone state</item>
<item>add voicemail</item>
<item>use sip</item>
<item>process outgoing call</item>
<item>fingerprint</item>
<item>body sensors</item>
<item>read cell broadcasts</item>
<item>mock location</item>
<item>read storage</item>
<item>write storage</item>
<item>turn on screen</item>
<item>get accounts</item>
<item>run in background</item>
</string-array>
<!-- User display names for app ops codes -->
......@@ -683,25 +669,11 @@
<item>Location</item>
<item>Get usage stats</item>
<item>Mute/unmute microphone</item>
<item>Show toast</item>
<item>Project media</item>
<item>Activate VPN</item>
<item>Write wallpaper</item>
<item>Assist structure</item>
<item>Assist screenshot</item>
<item>Read phone state</item>
<item>Add voicemail</item>
<item>Use sip</item>
<item>Process outgoing call</item>
<item>Fingerprint</item>
<item>Body sensors</item>
<item>Read cell broadcasts</item>
<item>Mock location</item>
<item>Read storage</item>
<item>Write storage</item>
<item>Turn on screen</item>
<item>Get accounts</item>
<item>Run in background</item>
</string-array>
<!-- Titles for the list of long press timeout options. -->
......
......@@ -29,4 +29,171 @@
<item>2</item>
<item>3</item>
</string-array>
<!-- Names of categories of app ops tabs - extension of AOSP -->
<string-array name="app_ops_categories_cm" translatable="false">
<item>@string/app_ops_categories_location</item>
<item>@string/app_ops_categories_personal</item>
<item>@string/app_ops_categories_messaging</item>
<item>@string/app_ops_categories_media</item>
<item>@string/app_ops_categories_device</item>
<item>@string/app_ops_categories_bootup</item>
<item>@string/app_ops_categories_su</item>
</string-array>
<!-- User display names for app ops codes - extension of AOSP -->
<string-array name="app_ops_summaries_cm" translatable="false">
<item>@string/app_ops_summaries_coarse_location</item>
<item>@string/app_ops_summaries_fine_location</item>
<item>@string/app_ops_summaries_gps</item>
<item>@string/app_ops_summaries_vibrate</item>
<item>@string/app_ops_summaries_read_contacts</item>
<item>@string/app_ops_summaries_modify_contacts</item>
<item>@string/app_ops_summaries_read_call_log</item>
<item>@string/app_ops_summaries_modify_call_log</item>
<item>@string/app_ops_summaries_read_calendar</item>
<item>@string/app_ops_summaries_modify_calendar</item>
<item>@string/app_ops_summaries_wifi_scan</item>
<item>@string/app_ops_summaries_notification</item>
<item>@string/app_ops_summaries_cell_scan</item>
<item>@string/app_ops_summaries_call_phone</item>
<item>@string/app_ops_summaries_read_sms</item>
<item>@string/app_ops_summaries_write_sms</item>
<item>@string/app_ops_summaries_receive_sms</item>
<item>@string/app_ops_summaries_receive_emergency_sms</item>
<item>@string/app_ops_summaries_receive_mms</item>
<item>@string/app_ops_summaries_receive_wap_push</item>
<item>@string/app_ops_summaries_send_sms</item>
<item>@string/app_ops_summaries_read_icc_sms</item>
<item>@string/app_ops_summaries_write_icc_sms</item>
<item>@string/app_ops_summaries_modify_settings</item>
<item>@string/app_ops_summaries_draw_on_top</item>
<item>@string/app_ops_summaries_access_notifications</item>
<item>@string/app_ops_summaries_camera</item>
<item>@string/app_ops_summaries_record_audio</item>
<item>@string/app_ops_summaries_play_audio</item>
<item>@string/app_ops_summaries_read_clipboard</item>
<item>@string/app_ops_summaries_modify_clipboard</item>
<item>@string/app_ops_summaries_media_buttons</item>
<item>@string/app_ops_summaries_audio_focus</item>
<item>@string/app_ops_summaries_master_volume</item>
<item>@string/app_ops_summaries_voice_volume</item>
<item>@string/app_ops_summaries_ring_volume</item>
<item>@string/app_ops_summaries_media_volume</item>
<item>@string/app_ops_summaries_alarm_volume</item>
<item>@string/app_ops_summaries_notification_volume</item>
<item>@string/app_ops_summaries_bluetooth_volume</item>
<item>@string/app_ops_summaries_keep_awake</item>
<item>@string/app_ops_summaries_monitor_location</item>
<item>@string/app_ops_summaries_monitor_high_power_location</item>
<item>@string/app_ops_summaries_get_usage_stats</item>
<item>@string/app_ops_summaries_mute_unmute_microphone</item>
<item>@string/app_ops_summaries_toast_window</item>
<item>@string/app_ops_summaries_project_media</item>
<item>@string/app_ops_summaries_activate_vpn</item>
<item>@string/app_ops_summaries_write_wallpaper</item>
<item>@string/app_ops_summaries_assist_structure</item>
<item>@string/app_ops_summaries_assist_screenshot</item>
<item>@string/app_ops_summaries_read_phone_state</item>
<item>@string/app_ops_summaries_add_voicemail</item>
<item>@string/app_ops_summaries_use_sip</item>
<item>@string/app_ops_summaries_make_call</item>
<item>@string/app_ops_summaries_use_fingerprint</item>
<item>@string/app_ops_summaries_use_body_sensors</item>
<item>@string/app_ops_summaries_read_cell_broadcasts</item>
<item>@string/app_ops_summaries_mock_location</item>
<item>@string/app_ops_summaries_read_external_storage</item>
<item>@string/app_ops_summaries_write_external_storage</item>
<item>@string/app_ops_summaries_turn_screen_on</item>
<item>@string/app_ops_summaries_get_accounts</item>
<item>@string/app_ops_summaries_run_in_background</item>
<item>@string/app_ops_summaries_toggle_wifi</item>
<item>@string/app_ops_summaries_toggle_bluetooth</item>
<item>@string/app_ops_summaries_start_at_boot</item>
<item>@string/app_ops_summaries_toggle_nfc</item>
<item>@string/app_ops_summaries_toggle_mobile_data</item>
<item>@string/app_ops_summaries_superuser</item>
</string-array>
<!-- User display names for app ops codes - extension of AOSP -->
<string-array name="app_ops_labels_cm" translatable="false">
<item>@string/app_ops_labels_coarse_location</item>
<item>@string/app_ops_labels_fine_location</item>
<item>@string/app_ops_labels_gps</item>
<item>@string/app_ops_labels_vibrate</item>
<item>@string/app_ops_labels_read_contacts</item>
<item>@string/app_ops_labels_modify_contacts</item>
<item>@string/app_ops_labels_read_call_log</item>
<item>@string/app_ops_labels_modify_call_log</item>
<item>@string/app_ops_labels_read_calendar</item>
<item>@string/app_ops_labels_modify_calendar</item>
<item>@string/app_ops_labels_wifi_scan</item>
<item>@string/app_ops_labels_notification</item>
<item>@string/app_ops_labels_cell_scan</item>
<item>@string/app_ops_labels_call_phone</item>
<item>@string/app_ops_labels_read_sms</item>
<item>@string/app_ops_labels_write_sms</item>
<item>@string/app_ops_labels_receive_sms</item>
<item>@string/app_ops_labels_receive_emergency_sms</item>
<item>@string/app_ops_labels_receive_mms</item>
<item>@string/app_ops_labels_receive_wap_push</item>
<item>@string/app_ops_labels_send_sms</item>
<item>@string/app_ops_labels_read_icc_sms</item>
<item>@string/app_ops_labels_write_icc_sms</item>
<item>@string/app_ops_labels_modify_settings</item>
<item>@string/app_ops_labels_draw_on_top</item>
<item>@string/app_ops_labels_access_notifications</item>
<item>@string/app_ops_labels_camera</item>
<item>@string/app_ops_labels_record_audio</item>
<item>@string/app_ops_labels_play_audio</item>
<item>@string/app_ops_labels_read_clipboard</item>
<item>@string/app_ops_labels_modify_clipboard</item>
<item>@string/app_ops_labels_media_buttons</item>
<item>@string/app_ops_labels_audio_focus</item>
<item>@string/app_ops_labels_master_volume</item>
<item>@string/app_ops_labels_voice_volume</item>
<item>@string/app_ops_labels_ring_volume</item>
<item>@string/app_ops_labels_media_volume</item>
<item>@string/app_ops_labels_alarm_volume</item>
<item>@string/app_ops_labels_notification_volume</item>
<item>@string/app_ops_labels_bluetooth_volume</item>
<item>@string/app_ops_labels_keep_awake</item>
<item>@string/app_ops_labels_monitor_location</item>
<item>@string/app_ops_labels_monitor_high_power_location</item>
<item>@string/app_ops_labels_get_usage_stats</item>
<item>@string/app_ops_labels_mute_unmute_microphone</item>
<item>@string/app_ops_labels_toast_window</item>
<item>@string/app_ops_labels_project_media</item>
<item>@string/app_ops_labels_activate_vpn</item>
<item>@string/app_ops_labels_write_wallpaper</item>
<item>@string/app_ops_labels_assist_structure</item>
<item>@string/app_ops_labels_assist_screenshot</item>
<item>@string/app_ops_labels_read_phone_state</item>
<item>@string/app_ops_labels_add_voicemail</item>
<item>@string/app_ops_labels_use_sip</item>
<item>@string/app_ops_labels_make_call</item>
<item>@string/app_ops_labels_use_fingerprint</item>
<item>@string/app_ops_labels_use_body_sensors</item>
<item>@string/app_ops_labels_read_cell_broadcasts</item>
<item>@string/app_ops_labels_mock_location</item>
<item>@string/app_ops_labels_read_external_storage</item>
<item>@string/app_ops_labels_write_external_storage</item>
<item>@string/app_ops_labels_turn_screen_on</item>
<item>@string/app_ops_labels_get_accounts</item>
<item>@string/app_ops_labels_run_in_background</item>
<item>@string/app_ops_labels_toggle_wifi</item>
<item>@string/app_ops_labels_toggle_bluetooth</item>
<item>@string/app_ops_labels_start_at_boot</item>
<item>@string/app_ops_labels_toggle_nfc</item>
<item>@string/app_ops_labels_toggle_mobile_data</item>
<item>@string/app_ops_labels_superuser</item>
</string-array>
<!-- App ops permissions -->
<string-array name="app_ops_permissions">
<item>@string/app_ops_permissions_allowed</item>
<item>@string/app_ops_permissions_ignored</item>
<item>@string/app_ops_permissions_always_ask</item>
</string-array>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2013-2014 The CyanogenMod 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.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<plurals name="app_ops_count">
<item quantity="one">once</item>
<item quantity="other">%d times</item>
</plurals>
</resources>
This diff is collapsed.
......@@ -359,7 +359,8 @@ public class AppOpsCategory extends ListFragment implements
SettingsActivity sa = (SettingsActivity) getActivity();
sa.startPreferencePanel(AppOpsDetails.class.getName(), args,
R.string.app_ops_settings, null, this, RESULT_APP_DETAILS);
org.cyanogenmod.platform.internal.R.string.privacy_guard_manager_title,
null, this, RESULT_APP_DETAILS);
}
@Override public void onListItemClick(ListView l, View v, int position, long id) {
......
......@@ -32,9 +32,11 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TextView;
......@@ -59,6 +61,41 @@ public class AppOpsDetails extends InstrumentedFragment {
private View mRootView;
private LinearLayout mOperationsSection;
private final int MODE_ALLOWED = 0;
private final int MODE_IGNORED = 1;
private final int MODE_ASK = 2;
private int modeToPosition (int mode) {
switch(mode) {
case AppOpsManager.MODE_ALLOWED:
return MODE_ALLOWED;
case AppOpsManager.MODE_IGNORED:
return MODE_IGNORED;
case AppOpsManager.MODE_ASK:
return MODE_ASK;
};
return MODE_IGNORED;
}
private int positionToMode (int position) {
switch(position) {
case MODE_ALLOWED:
return AppOpsManager.MODE_ALLOWED;
case MODE_IGNORED:
return AppOpsManager.MODE_IGNORED;
case MODE_ASK:
return AppOpsManager.MODE_ASK;
};
return AppOpsManager.MODE_IGNORED;
}
private boolean isPlatformSigned() {
final int match = mPm.checkSignatures("android", mPackageInfo.packageName);
return match >= PackageManager.SIGNATURE_MATCH;
}
// Utility method to set application label and icon.
private void setAppLabelAndIcon(PackageInfo pkgInfo) {
final View appSnippet = mRootView.findViewById(R.id.app_snippet);
......@@ -101,7 +138,15 @@ public class AppOpsDetails extends InstrumentedFragment {
mOperationsSection.removeAllViews();
String lastPermGroup = "";
boolean isPlatformSigned = isPlatformSigned();
for (AppOpsState.OpsTemplate tpl : AppOpsState.ALL_TEMPLATES) {
/* If we are platform signed, only show the root switch, this
* one is safe to toggle while other permission-based ones could
* certainly cause system-wide problems
*/
if (isPlatformSigned && tpl != AppOpsState.SU_TEMPLATE) {
continue;
}
List<AppOpsState.AppOpEntry> entries = mState.buildState(tpl,
mPackageInfo.applicationInfo.uid, mPackageInfo.packageName);
for (final AppOpsState.AppOpEntry entry : entries) {
......@@ -126,20 +171,57 @@ public class AppOpsDetails extends InstrumentedFragment {
}
((TextView)view.findViewById(R.id.op_name)).setText(
entry.getSwitchText(mState));
((TextView)view.findViewById(R.id.op_counts)).setText(
entry.getCountsText(res));
((TextView)view.findViewById(R.id.op_time)).setText(
entry.getTimeText(res, true));
Switch sw = (Switch)view.findViewById(R.id.switchWidget);
Spinner sp = (Spinner) view.findViewById(R.id.spinnerWidget);
sp.setVisibility(View.INVISIBLE);
Switch sw = (Switch) view.findViewById(R.id.switchWidget);
sw.setVisibility(View.INVISIBLE);
final int switchOp = AppOpsManager.opToSwitch(firstOp.getOp());
sw.setChecked(mAppOps.checkOp(switchOp, entry.getPackageOps().getUid(),
entry.getPackageOps().getPackageName()) == AppOpsManager.MODE_ALLOWED);
sw.setOnCheckedChangeListener(new Switch.OnCheckedChangeListener() {
int mode = mAppOps.checkOp(switchOp, entry.getPackageOps().getUid(),
entry.getPackageOps().getPackageName());
sp.setSelection(modeToPosition(mode));
sp.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
boolean firstMode = true;
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
public void onItemSelected(AdapterView<?> parentView, View selectedItemView,
int position, long id) {
if (firstMode) {
firstMode = false;
return;
}
mAppOps.setMode(switchOp, entry.getPackageOps().getUid(),
entry.getPackageOps().getPackageName(), isChecked
? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
entry.getPackageOps().getPackageName(), positionToMode(position));
}
@Override
public void onNothingSelected(AdapterView<?> parentView) {
// Do nothing
}
});
sw.setChecked(mAppOps.checkOp(switchOp, entry.getPackageOps()
.getUid(), entry.getPackageOps().getPackageName()) == AppOpsManager.MODE_ALLOWED);
sw.setOnCheckedChangeListener(new Switch.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
mAppOps.setMode(switchOp, entry.getPackageOps()
.getUid(), entry.getPackageOps()
.getPackageName(),
isChecked ? AppOpsManager.MODE_ALLOWED
: AppOpsManager.MODE_IGNORED);
}
});
if (AppOpsManager.isStrictOp(switchOp)) {
sp.setVisibility(View.VISIBLE);
} else {
sw.setVisibility(View.VISIBLE);
}
}
}
......
/**
* Copyright (C) 2015 The CyanogenMod 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.settings.applications;
import android.content.Intent;
import android.preference.PreferenceActivity;
public class AppOpsDetailsTop extends PreferenceActivity {
@Override
public Intent getIntent() {
Intent modIntent = new Intent(super.getIntent());
modIntent.putExtra(EXTRA_SHOW_FRAGMENT, AppOpsDetails.class.getName());
modIntent.putExtra(EXTRA_NO_HEADERS, true);
return modIntent;
}
@Override
protected boolean isValidFragment(String fragmentName) {
if (AppOpsDetails.class.getName().equals(fragmentName)) return true;
return false;
}
}
......@@ -16,19 +16,34 @@
package com.android.settings.applications;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AppOpsManager;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.res.TypedArray;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceFrameLayout;
import android.support.v13.app.FragmentPagerAdapter;
import android.support.v4.view.PagerTabStrip;
import android.support.v4.view.ViewPager;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import java.util.ArrayList;
import java.util.List;
import com.android.settings.DevelopmentSettings;
import com.android.settings.InstrumentedFragment;
import com.android.settings.R;
......@@ -40,14 +55,12 @@ public class AppOpsSummary extends InstrumentedFragment {
private View mRootView;
private ViewPager mViewPager;
private MyPagerAdapter mAdapter;
private Activity mActivity;
private SharedPreferences mPreferences;
CharSequence[] mPageNames;
static AppOpsState.OpsTemplate[] sPageTemplates = new AppOpsState.OpsTemplate[] {
AppOpsState.LOCATION_TEMPLATE,
AppOpsState.PERSONAL_TEMPLATE,
AppOpsState.MESSAGING_TEMPLATE,
AppOpsState.MEDIA_TEMPLATE,
AppOpsState.DEVICE_TEMPLATE
};
int mCurPos;
......@@ -57,19 +70,21 @@ public class AppOpsSummary extends InstrumentedFragment {
}
class MyPagerAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener {
private AppOpsState.OpsTemplate[] mPageTemplates;
public MyPagerAdapter(FragmentManager fm) {
public MyPagerAdapter(FragmentManager fm, AppOpsState.OpsTemplate[] templates) {
super(fm);
mPageTemplates = templates;
}
@Override
public Fragment getItem(int position) {
return new AppOpsCategory(sPageTemplates[position]);
return new AppOpsCategory(mPageTemplates[position]);
}
@Override
public int getCount() {
return sPageTemplates.length;
return mPageTemplates.length;
}
@Override
......@@ -86,6 +101,10 @@ public class AppOpsSummary extends InstrumentedFragment {
mCurPos = position;
}
public int getCurrentPage() {
return mCurPos;
}
@Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
......@@ -94,6 +113,14 @@ public class AppOpsSummary extends InstrumentedFragment {
}
}
private void resetAdapter() {
// trigger adapter load, preserving the selected page
int curPos = mAdapter.getCurrentPage();
mViewPager.setAdapter(mAdapter);
mViewPager.setOnPageChangeListener(mAdapter);
mViewPager.setCurrentItem(curPos);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// initialize the inflater
......@@ -104,22 +131,20 @@ public class AppOpsSummary extends InstrumentedFragment {
mContentContainer = container;
mRootView = rootView;
mPageNames = getResources().getTextArray(R.array.app_ops_categories);
mPageNames = getResources().getTextArray(R.array.app_ops_categories_cm);
mViewPager = (ViewPager) rootView.findViewById(R.id.pager);
MyPagerAdapter adapter = new MyPagerAdapter(getChildFragmentManager());
mViewPager.setAdapter(adapter);
mViewPager.setOnPageChangeListener(adapter);
mAdapter = new MyPagerAdapter(getChildFragmentManager(),
filterTemplates(AppOpsState.ALL_TEMPLATES));
mViewPager.setAdapter(mAdapter);
mViewPager.setOnPageChangeListener(mAdapter);
PagerTabStrip tabs = (PagerTabStrip) rootView.findViewById(R.id.tabs);