diff options
author | Danesh M <daneshm90@gmail.com> | 2016-03-07 15:17:59 -0800 |
---|---|---|
committer | Danesh M <daneshm90@gmail.com> | 2016-03-21 11:44:50 -0700 |
commit | a3549a2715e47ce07297315586ea9c5798da2997 (patch) | |
tree | 895cfd77ae3684f4e3d1c44410d33826246875a0 | |
parent | f5dea70443a1c0643be50cf8058ddbfff477712f (diff) | |
download | packages_apps_Settings-a3549a2715e47ce07297315586ea9c5798da2997.zip packages_apps_Settings-a3549a2715e47ce07297315586ea9c5798da2997.tar.gz packages_apps_Settings-a3549a2715e47ce07297315586ea9c5798da2997.tar.bz2 |
Settings : Add per app internet/data control
CYAN-3976
CRACKLING-834
Change-Id: I13192df837c057b5cadde8f31532e12daaf3c1b0
-rw-r--r-- | res/layout/app_ops_details_item.xml | 81 | ||||
-rw-r--r-- | res/layout/preference_category_material.xml | 27 | ||||
-rw-r--r-- | res/values/cm_strings.xml | 6 | ||||
-rw-r--r-- | src/com/android/settings/applications/AppOpsDetails.java | 54 | ||||
-rw-r--r-- | src/com/android/settings/privacyguard/AppInfoLoader.java | 3 | ||||
-rw-r--r-- | src/com/android/settings/privacyguard/PrivacyGuardManager.java | 20 |
6 files changed, 143 insertions, 48 deletions
diff --git a/res/layout/app_ops_details_item.xml b/res/layout/app_ops_details_item.xml index eb206ae..beb04f3 100644 --- a/res/layout/app_ops_details_item.xml +++ b/res/layout/app_ops_details_item.xml @@ -17,68 +17,62 @@ */ --> -<GridLayout xmlns:android="http://schemas.android.com/apk/res/android" +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="?android:attr/listPreferredItemHeight" android:paddingStart="?android:attr/listPreferredItemPaddingStart" android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" android:paddingTop="8dip" - android:paddingBottom="8dip" - android:columnCount="3"> + android:paddingBottom="8dip"> <ImageView android:id="@+id/op_icon" android:layout_width="@android:dimen/app_icon_size" android:layout_height="@android:dimen/app_icon_size" - android:layout_column="0" - android:layout_row="0" - android:layout_rowSpan="2" android:layout_marginEnd="8dip" android:scaleType="centerInside" android:contentDescription="@null" /> - <TextView - 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" - android:ellipsize="marquee" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textAlignment="viewStart" /> - - <TextView - android:id="@+id/op_time" - android:layout_column="1" - android:layout_row="1" + <LinearLayout + android:orientation="vertical" android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_gravity="fill_horizontal|top" - android:textAppearance="?android:attr/textAppearanceSmall" - android:textAlignment="viewStart" /> + android:layout_weight="1" + android:layout_height="wrap_content"> + <TextView + android:id="@+id/op_name" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="fill_horizontal" + android:layout_marginTop="2dip" + android:singleLine="true" + android:ellipsize="marquee" + android:textAppearance="?android:attr/textAppearanceMedium" + 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" /> + <TextView + android:id="@+id/op_time" + android:layout_width="match_parent" + 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_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="fill_horizontal|top" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textAlignment="viewStart" /> + </LinearLayout> <Spinner android:id="@+id/spinnerWidget" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center_vertical" + android:layout_gravity="end" android:layout_marginStart="8dip" - android:layout_column="2" - android:layout_row="0" - android:layout_rowSpan="3" android:padding="8dip" android:focusable="false" android:entries="@+array/app_ops_permissions" /> @@ -87,14 +81,9 @@ android:id="@+id/switchWidget" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center_vertical" + android:layout_gravity="end" 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> +</LinearLayout> diff --git a/res/layout/preference_category_material.xml b/res/layout/preference_category_material.xml new file mode 100644 index 0000000..d528464 --- /dev/null +++ b/res/layout/preference_category_material.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<!-- Layout used for PreferenceCategory in a PreferenceActivity. --> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+android:id/title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="16dip" + android:textAppearance="@*android:style/TextAppearance.Material.Body2" + android:textColor="@*android:color/preference_category_text_color" + android:paddingStart="?*android:attr/listPreferredItemPaddingStart" + android:paddingEnd="?*android:attr/listPreferredItemPaddingEnd" + android:paddingTop="16dip" /> diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml index 1328144..17099ec 100644 --- a/res/values/cm_strings.xml +++ b/res/values/cm_strings.xml @@ -1156,4 +1156,10 @@ <string name="battery_info_status_charging_dock_ac">Charging on dock AC</string> <!-- [CHAR_LIMIT=20] Battery use screen. Battery status shown in chart label when charging over Dock USB. --> <string name="battery_info_status_charging_dock_usb">Charging over dock USB</string> + + <string name="restrict_app_wlan_title">Disable app wifi usage</string> + <string name="restrict_app_wlan_summary">Prevent app from using wifi data connection</string> + <string name="restrict_app_cellular_title">Disable app cellular usage</string> + <string name="restrict_app_cellular_summary">Prevent app from using cellular data connection</string> + <string name="privacy_guard_internet_category">Internet</string> </resources> diff --git a/src/com/android/settings/applications/AppOpsDetails.java b/src/com/android/settings/applications/AppOpsDetails.java index 12da8b8..af80367 100644 --- a/src/com/android/settings/applications/AppOpsDetails.java +++ b/src/com/android/settings/applications/AppOpsDetails.java @@ -16,6 +16,7 @@ package com.android.settings.applications; +import android.Manifest; import android.app.Activity; import android.app.AppOpsManager; import android.app.Fragment; @@ -28,6 +29,7 @@ import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; import android.content.res.Resources; import android.graphics.drawable.Drawable; +import android.net.NetworkPolicyManager; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; @@ -49,6 +51,9 @@ import com.android.settings.Utils; import java.util.List; +import static android.net.NetworkPolicyManager.POLICY_REJECT_ON_DATA; +import static android.net.NetworkPolicyManager.POLICY_REJECT_ON_WLAN; + public class AppOpsDetails extends InstrumentedFragment { static final String TAG = "AppOpsDetails"; @@ -61,6 +66,7 @@ public class AppOpsDetails extends InstrumentedFragment { private LayoutInflater mInflater; private View mRootView; private LinearLayout mOperationsSection; + private NetworkPolicyManager mPolicyManager; private final int MODE_ALLOWED = 0; private final int MODE_IGNORED = 1; @@ -178,9 +184,9 @@ public class AppOpsDetails extends InstrumentedFragment { entry.getTimeText(res, true)); Spinner sp = (Spinner) view.findViewById(R.id.spinnerWidget); - sp.setVisibility(View.INVISIBLE); + sp.setVisibility(View.GONE); Switch sw = (Switch) view.findViewById(R.id.switchWidget); - sw.setVisibility(View.INVISIBLE); + sw.setVisibility(View.GONE); final int switchOp = AppOpsManager.opToSwitch(firstOp.getOp()); int mode = mAppOps.checkOp(switchOp, entry.getPackageOps().getUid(), @@ -226,9 +232,52 @@ public class AppOpsDetails extends InstrumentedFragment { } } + if (mPm.checkPermission(Manifest.permission.INTERNET, mPackageInfo.packageName) + == PackageManager.PERMISSION_GRANTED) { + TextView internetCategory = (TextView) mInflater.inflate( + R.layout.preference_category_material, null); + internetCategory.setText(R.string.privacy_guard_internet_category); + mOperationsSection.addView(internetCategory); + + addInternetSwitch(POLICY_REJECT_ON_WLAN); + addInternetSwitch(POLICY_REJECT_ON_DATA); + } + return true; } + private void addInternetSwitch(final int policy) { + // Add internet category permissions + final View view = mInflater.inflate(R.layout.app_ops_details_item, + mOperationsSection, false); + mOperationsSection.addView(view); + + ((TextView)view.findViewById(R.id.op_name)).setText( + policy == POLICY_REJECT_ON_DATA ? R.string.restrict_app_cellular_title : + R.string.restrict_app_wlan_title); + view.findViewById(R.id.op_counts).setVisibility(View.INVISIBLE); + view.findViewById(R.id.op_time).setVisibility(View.INVISIBLE); + view.findViewById(R.id.spinnerWidget).setVisibility(View.GONE); + + Switch sw = (Switch) view.findViewById(R.id.switchWidget); + sw.setChecked((mPolicyManager.getUidPolicy( + mPackageInfo.applicationInfo.uid) & policy) != 0); + sw.setTag(policy); + sw.setVisibility(View.VISIBLE); + sw.setOnCheckedChangeListener(new Switch.OnCheckedChangeListener() { + public void onCheckedChanged(CompoundButton buttonView, + boolean isChecked) { + if (isChecked) { + mPolicyManager.addUidPolicy(mPackageInfo.applicationInfo.uid, + policy); + } else { + mPolicyManager.removeUidPolicy(mPackageInfo.applicationInfo.uid, + policy); + } + } + }); + } + private void setIntentAndFinish(boolean finish, boolean appChanged) { Intent intent = new Intent(); intent.putExtra(ManageApplications.APP_CHG, appChanged); @@ -245,6 +294,7 @@ public class AppOpsDetails extends InstrumentedFragment { mPm = getActivity().getPackageManager(); mInflater = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); mAppOps = (AppOpsManager)getActivity().getSystemService(Context.APP_OPS_SERVICE); + mPolicyManager = NetworkPolicyManager.from(getActivity()); retrieveAppEntry(); diff --git a/src/com/android/settings/privacyguard/AppInfoLoader.java b/src/com/android/settings/privacyguard/AppInfoLoader.java index 6efd7a5..520bd20 100644 --- a/src/com/android/settings/privacyguard/AppInfoLoader.java +++ b/src/com/android/settings/privacyguard/AppInfoLoader.java @@ -15,6 +15,7 @@ */ package com.android.settings.privacyguard; +import android.Manifest; import android.app.AppOpsManager; import android.content.AsyncTaskLoader; import android.content.Context; @@ -104,6 +105,8 @@ import java.util.List; app.uid = info.applicationInfo.uid; app.privacyGuardEnabled = mAppOps.getPrivacyGuardSettingForPackage( app.uid, app.packageName); + app.hasInternetPermission = mPm.checkPermission(Manifest.permission.INTERNET, + app.packageName) == PackageManager.PERMISSION_GRANTED; apps.add(app); } diff --git a/src/com/android/settings/privacyguard/PrivacyGuardManager.java b/src/com/android/settings/privacyguard/PrivacyGuardManager.java index adbe8cc..4cc8214 100644 --- a/src/com/android/settings/privacyguard/PrivacyGuardManager.java +++ b/src/com/android/settings/privacyguard/PrivacyGuardManager.java @@ -16,7 +16,10 @@ package com.android.settings.privacyguard; +import android.Manifest; import android.app.FragmentTransaction; +import android.content.pm.PackageManager; +import android.net.NetworkPolicyManager; import android.view.animation.AnimationUtils; import android.app.Activity; import android.app.AlertDialog; @@ -87,6 +90,7 @@ public class PrivacyGuardManager extends Fragment // Privacy Guard Fragment private final static String PRIVACY_GUARD_FRAGMENT_TAG = "privacy_guard_fragment"; + private NetworkPolicyManager mPolicyManager; // holder for package data passed into the adapter public static final class AppInfo { @@ -95,6 +99,13 @@ public class PrivacyGuardManager extends Fragment boolean enabled; boolean privacyGuardEnabled; int uid; + boolean hasInternetPermission; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mPolicyManager = NetworkPolicyManager.from(getActivity()); } @Override @@ -280,6 +291,15 @@ public class PrivacyGuardManager extends Fragment app.privacyGuardEnabled = !app.privacyGuardEnabled; mAppOps.setPrivacyGuardSettingForPackage(app.uid, app.packageName, app.privacyGuardEnabled); + if (app.hasInternetPermission) { + if (app.privacyGuardEnabled) { + mPolicyManager.addUidPolicy(app.uid, NetworkPolicyManager.POLICY_REJECT_ON_DATA); + mPolicyManager.addUidPolicy(app.uid, NetworkPolicyManager.POLICY_REJECT_ON_WLAN); + } else { + mPolicyManager.removeUidPolicy(app.uid, NetworkPolicyManager.POLICY_REJECT_ON_DATA); + mPolicyManager.removeUidPolicy(app.uid, NetworkPolicyManager.POLICY_REJECT_ON_WLAN); + } + } mAdapter.notifyDataSetChanged(); } |