• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.settings.applications;
17 
18 import static android.app.AppOpsManager.MODE_ALLOWED;
19 import static android.app.AppOpsManager.MODE_ERRORED;
20 import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
21 
22 import android.app.AlertDialog;
23 import android.app.AppOpsManager;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.os.Bundle;
27 import android.provider.Settings;
28 import android.support.v14.preference.SwitchPreference;
29 import android.support.v7.preference.Preference;
30 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
31 
32 import com.android.internal.annotations.VisibleForTesting;
33 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
34 import com.android.settings.R;
35 import com.android.settings.overlay.FeatureFactory;
36 
37 public class PictureInPictureDetails extends AppInfoWithHeader
38         implements OnPreferenceChangeListener {
39 
40     private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch";
41     private static final String KEY_APP_OPS_SETTINGS_PREFS = "app_ops_settings_preference";
42     private static final String KEY_APP_OPS_SETTINGS_DESC = "app_ops_settings_description";
43     private static final String LOG_TAG = "PictureInPictureDetails";
44 
45     private SwitchPreference mSwitchPref;
46     private Preference mOverlayDesc;
47     private Intent mSettingsIntent;
48 
49     @Override
onCreate(Bundle savedInstanceState)50     public void onCreate(Bundle savedInstanceState) {
51         super.onCreate(savedInstanceState);
52 
53         // find preferences
54         addPreferencesFromResource(R.xml.app_ops_permissions_details);
55         mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH);
56         mOverlayDesc = findPreference(KEY_APP_OPS_SETTINGS_DESC);
57         getPreferenceScreen().removePreference(findPreference(KEY_APP_OPS_SETTINGS_PREFS));
58 
59         // set title/summary for all of them
60         getPreferenceScreen().setTitle(R.string.picture_in_picture_app_detail_title);
61         mSwitchPref.setTitle(R.string.picture_in_picture_app_detail_switch);
62         mOverlayDesc.setSummary(R.string.picture_in_picture_app_detail_summary);
63 
64         // install event listeners
65         mSwitchPref.setOnPreferenceChangeListener(this);
66 
67         mSettingsIntent = new Intent(Intent.ACTION_MAIN)
68                 .setAction(Settings.ACTION_PICTURE_IN_PICTURE_SETTINGS);
69     }
70 
71     @Override
onPreferenceChange(Preference preference, Object newValue)72     public boolean onPreferenceChange(Preference preference, Object newValue) {
73         if (preference == mSwitchPref) {
74             logSpecialPermissionChange((Boolean) newValue, mPackageName);
75             setEnterPipStateForPackage(getActivity(), mPackageInfo.applicationInfo.uid, mPackageName,
76                     (Boolean) newValue);
77             return true;
78         }
79         return false;
80     }
81 
82     @Override
refreshUi()83     protected boolean refreshUi() {
84         boolean isAllowed = getEnterPipStateForPackage(getActivity(),
85                 mPackageInfo.applicationInfo.uid, mPackageName);
86         mSwitchPref.setChecked(isAllowed);
87         return true;
88     }
89 
90     @Override
createDialog(int id, int errorCode)91     protected AlertDialog createDialog(int id, int errorCode) {
92         return null;
93     }
94 
95     @Override
getMetricsCategory()96     public int getMetricsCategory() {
97         return MetricsEvent.SETTINGS_MANAGE_PICTURE_IN_PICTURE;
98     }
99 
100     /**
101      * Sets whether the app associated with the given {@param packageName} is allowed to enter
102      * picture-in-picture.
103      */
setEnterPipStateForPackage(Context context, int uid, String packageName, boolean value)104     static void setEnterPipStateForPackage(Context context, int uid, String packageName,
105             boolean value) {
106         final AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
107         final int newMode = value ? MODE_ALLOWED : MODE_ERRORED;
108         appOps.setMode(OP_PICTURE_IN_PICTURE, uid, packageName, newMode);
109     }
110 
111     /**
112      * @return whether the app associated with the given {@param packageName} is allowed to enter
113      *         picture-in-picture.
114      */
getEnterPipStateForPackage(Context context, int uid, String packageName)115     static boolean getEnterPipStateForPackage(Context context, int uid, String packageName) {
116         final AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
117         return appOps.checkOpNoThrow(OP_PICTURE_IN_PICTURE, uid, packageName) == MODE_ALLOWED;
118     }
119 
120     /**
121      * @return the summary for the current state of whether the app associated with the given
122      *         {@param packageName} is allowed to enter picture-in-picture.
123      */
getPreferenceSummary(Context context, int uid, String packageName)124     static int getPreferenceSummary(Context context, int uid, String packageName) {
125         final boolean enabled = PictureInPictureDetails.getEnterPipStateForPackage(context, uid,
126                 packageName);
127         return enabled ? R.string.picture_in_picture_on : R.string.picture_in_picture_off;
128     }
129 
130     @VisibleForTesting
logSpecialPermissionChange(boolean newState, String packageName)131     void logSpecialPermissionChange(boolean newState, String packageName) {
132         int logCategory = newState
133                 ? MetricsEvent.APP_PICTURE_IN_PICTURE_ALLOW
134                 : MetricsEvent.APP_PICTURE_IN_PICTURE_DENY;
135         FeatureFactory.getFactory(getContext())
136                 .getMetricsFeatureProvider().action(getContext(), logCategory, packageName);
137     }
138 }
139