• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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 
17 package com.android.tv.settings.system;
18 
19 import com.android.tv.settings.R;
20 import com.android.tv.settings.users.RestrictedProfileDialogFragment;
21 import com.android.tv.settings.util.SettingsHelper;
22 import com.android.tv.settings.dialog.DialogFragment;
23 import com.android.tv.settings.dialog.DialogFragment.Action;
24 
25 import android.app.Activity;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.pm.PackageManager;
29 import android.content.pm.ResolveInfo;
30 import android.os.Bundle;
31 import android.os.UserManager;
32 import android.provider.Settings;
33 
34 import java.util.ArrayList;
35 import java.util.List;
36 
37 /**
38  * Manages app security preferences. TODO: get a better icon from UX TODO: implement Notification
39  * listener settings
40  */
41 public class SecurityActivity extends Activity implements Action.Listener {
42 
43     private static final int CHECK_SET_ID = 1;
44     private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
45     private static final String ACTION_RESTRICTED_PROFILE = "action_restricted_profile";
46     private static final String ACTION_SECURITY_UNKNOWN_SOURCES = "action_security_unknown_sources";
47     private static final String ACTION_SECURITY_UNKNOWN_SOURCES_OFF =
48             "action_security_unknown_sources_off";
49     private static final String ACTION_SECURITY_VERIFY_APPS = "action_security_verify_apps";
50     private static final String ACTION_SECURITY_VERIFY_APPS_ON = "action_security_verify_apps_on";
51     private static final String ACTION_SECURITY_VERIFY_APPS_OFF = "action_security_verify_apps_off";
52     private static final String ACTION_SECURITY_UNKNOWN_SOURCES_CONFIRM =
53             "action_security_verify_apps_confirm";
54     private static final String ACTION_SECURITY_UNKNOWN_SOURCES_CONFIRM_OK =
55             "action_security_verify_apps_confirm_ok";
56     private static final String ACTION_SECURITY_UNKNOWN_SOURCES_CONFIRM_CANCEL =
57             "action_security_verify_apps_confirm_cancel";
58 
59     private static final String TAG_RESTRICTED_PROFILE_SIDECAR_FRAGMENT =
60             "restricted_profile_sidecar";
61 
62     private SettingsHelper mHelper;
63     private boolean mVerifierInstalled;
64     private DialogFragment mMainMenuDialogFragment;
65 
66     @Override
onCreate(Bundle savedInstanceState)67     protected void onCreate(Bundle savedInstanceState) {
68         mHelper = new SettingsHelper(getApplicationContext());
69         mVerifierInstalled = isVerifierInstalled();
70         // Do this after setting up what's needed.
71         super.onCreate(savedInstanceState);
72         mMainMenuDialogFragment = new DialogFragment.Builder()
73                 .breadcrumb(getString(R.string.header_category_personal))
74                 .title(getString(R.string.system_security))
75                 .iconResourceId(R.drawable.ic_settings_security)
76                 .iconBackgroundColor(getResources().getColor(R.color.icon_background))
77                 .actions(getMainMenuActions()).build();
78         DialogFragment.add(getFragmentManager(), mMainMenuDialogFragment);
79     }
80 
81     @Override
onActionClicked(Action action)82     public void onActionClicked(Action action) {
83         if (ACTION_RESTRICTED_PROFILE.equals(action.getKey())) {
84             getFragmentManager().beginTransaction().add(new RestrictedProfileDialogFragment(),
85                     TAG_RESTRICTED_PROFILE_SIDECAR_FRAGMENT).commit();
86         } else if (ACTION_SECURITY_UNKNOWN_SOURCES.equals(action.getKey())) {
87             boolean isNonMarketAppsAllowed = isNonMarketAppsAllowed();
88             ArrayList<Action> actions = new ArrayList<>();
89             // Note we only use the check set id if the "on" is checked so if "off" is selected
90             // there is an animation of the check for "off".  We don't want the same behavior for
91             // "on" because it has to go through a confirmation sub-dialog.
92             actions.add(new Action.Builder()
93                     .key(ACTION_SECURITY_UNKNOWN_SOURCES_CONFIRM)
94                     .title(getString(R.string.settings_on))
95                     .checked(isNonMarketAppsAllowed)
96                     .checkSetId(isNonMarketAppsAllowed ? CHECK_SET_ID : 0)
97                     .build());
98             actions.add(new Action.Builder()
99                     .key(ACTION_SECURITY_UNKNOWN_SOURCES_OFF)
100                     .title(getString(R.string.settings_off))
101                     .checked(!isNonMarketAppsAllowed)
102                     .checkSetId(CHECK_SET_ID)
103                     .build());
104 
105             DialogFragment dialogFragment = new DialogFragment.Builder()
106                     .breadcrumb(getString(R.string.system_security))
107                     .title(getString(R.string.security_unknown_sources_title))
108                     .description(getString(R.string.security_unknown_sources_desc))
109                     .actions(actions)
110                     .build();
111             DialogFragment.add(getFragmentManager(), dialogFragment);
112         } else if (ACTION_SECURITY_UNKNOWN_SOURCES_OFF.equals(action.getKey())) {
113             setNonMarketAppsAllowed(false);
114             mMainMenuDialogFragment.setActions(getMainMenuActions());
115             getFragmentManager().popBackStack();
116         } else if (ACTION_SECURITY_UNKNOWN_SOURCES_CONFIRM.equals(action.getKey())) {
117             // No point in issuing the confirmation sub-dialog if we're already "on".
118             if (isNonMarketAppsAllowed()) {
119                 getFragmentManager().popBackStack();
120             } else {
121                 ArrayList<Action> actions = new ArrayList<>();
122                 actions.add(new Action.Builder()
123                         .key(ACTION_SECURITY_UNKNOWN_SOURCES_CONFIRM_OK)
124                         .title(getString(R.string.settings_ok))
125                         .build());
126                 actions.add(new Action.Builder()
127                         .key(ACTION_SECURITY_UNKNOWN_SOURCES_CONFIRM_CANCEL)
128                         .title(getString(R.string.settings_cancel))
129                         .build());
130 
131                 DialogFragment dialogFragment = new DialogFragment.Builder()
132                         .breadcrumb(getString(R.string.system_security))
133                         .title(getString(R.string.security_unknown_sources_title))
134                         .description(getString(R.string.security_unknown_sources_confirm_desc))
135                         .actions(actions)
136                         .build();
137                 DialogFragment.add(getFragmentManager(), dialogFragment);
138             }
139         } else if (ACTION_SECURITY_UNKNOWN_SOURCES_CONFIRM_OK.equals(action.getKey())) {
140             setNonMarketAppsAllowed(true);
141             mMainMenuDialogFragment.setActions(getMainMenuActions());
142             getFragmentManager().popBackStack();
143             getFragmentManager().popBackStack();
144         } else if (ACTION_SECURITY_UNKNOWN_SOURCES_CONFIRM_CANCEL.equals(action.getKey())) {
145             getFragmentManager().popBackStack();
146             getFragmentManager().popBackStack();
147         } else if (ACTION_SECURITY_VERIFY_APPS.equals(action.getKey())) {
148             boolean isVerifyAppsEnabled = mVerifierInstalled && isVerifyAppsEnabled();
149 
150             ArrayList<Action> actions = new ArrayList<>();
151             actions.add(new Action.Builder()
152                     .key(ACTION_SECURITY_VERIFY_APPS_ON)
153                     .title(getString(R.string.settings_on))
154                     .checked(isVerifyAppsEnabled)
155                     .checkSetId(CHECK_SET_ID)
156                     .build());
157             actions.add(new Action.Builder()
158                     .key(ACTION_SECURITY_VERIFY_APPS_OFF)
159                     .title(getString(R.string.settings_off))
160                     .checked(!isVerifyAppsEnabled)
161                     .checkSetId(CHECK_SET_ID)
162                     .build());
163 
164             DialogFragment dialogFragment = new DialogFragment.Builder()
165                     .breadcrumb(getString(R.string.system_security))
166                     .title(getString(R.string.security_verify_apps_title))
167                     .description(getString(R.string.security_verify_apps_desc))
168                     .actions(actions)
169                     .build();
170             DialogFragment.add(getFragmentManager(), dialogFragment);
171         } else if (ACTION_SECURITY_VERIFY_APPS_ON.equals(action.getKey())) {
172             setVerifyAppsEnabled(true);
173             mMainMenuDialogFragment.setActions(getMainMenuActions());
174             getFragmentManager().popBackStack();
175         } else if (ACTION_SECURITY_VERIFY_APPS_OFF.equals(action.getKey())) {
176             setVerifyAppsEnabled(false);
177             mMainMenuDialogFragment.setActions(getMainMenuActions());
178             getFragmentManager().popBackStack();
179         }
180     }
181 
getMainMenuActions()182     private ArrayList<Action> getMainMenuActions() {
183         boolean isNonMarketAppsAllowed = isNonMarketAppsAllowed();
184         ArrayList<Action> actions = new ArrayList<>();
185         actions.add(new Action.Builder()
186                 .key(ACTION_SECURITY_UNKNOWN_SOURCES)
187                 .title(getString(R.string.security_unknown_sources_title))
188                 .description(mHelper.getStatusStringFromBoolean(isNonMarketAppsAllowed()))
189                 .build());
190         if (showVerifierSetting()) {
191             actions.add(new Action.Builder()
192                     .key(ACTION_SECURITY_VERIFY_APPS)
193                     .title(getString(R.string.security_verify_apps_title))
194                     .description(mHelper.getStatusStringFromBoolean(isVerifyAppsEnabled()
195                             && mVerifierInstalled))
196                     .enabled(mVerifierInstalled)
197                     .build());
198         }
199         actions.add(new Action.Builder().key(ACTION_RESTRICTED_PROFILE)
200                 .title(getString(R.string.launcher_restricted_profile_app_name))
201                 .description(RestrictedProfileDialogFragment.getActionDescription(this))
202                 .build());
203         return actions;
204     }
205 
isNonMarketAppsAllowed()206     private boolean isNonMarketAppsAllowed() {
207         return Settings.Global.getInt(getContentResolver(),
208                 Settings.Global.INSTALL_NON_MARKET_APPS, 0) > 0;
209     }
210 
setNonMarketAppsAllowed(boolean enabled)211     private void setNonMarketAppsAllowed(boolean enabled) {
212         final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
213         if (um.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)) {
214             return;
215         }
216         // Change the system setting
217         Settings.Global.putInt(getContentResolver(), Settings.Global.INSTALL_NON_MARKET_APPS,
218                 enabled ? 1 : 0);
219     }
220 
isVerifyAppsEnabled()221     private boolean isVerifyAppsEnabled() {
222         return Settings.Global.getInt(getContentResolver(),
223                 Settings.Global.PACKAGE_VERIFIER_ENABLE, 1) > 0;
224     }
225 
setVerifyAppsEnabled(boolean enable)226     private void setVerifyAppsEnabled(boolean enable) {
227         Settings.Global.putInt(getContentResolver(), Settings.Global.PACKAGE_VERIFIER_ENABLE,
228                 enable ? 1 : 0);
229     }
230 
isVerifierInstalled()231     private boolean isVerifierInstalled() {
232         final PackageManager pm = getPackageManager();
233         final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
234         verification.setType(PACKAGE_MIME_TYPE);
235         verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
236         final List<ResolveInfo> receivers = pm.queryBroadcastReceivers(verification, 0);
237         return (receivers.size() > 0) ? true : false;
238     }
239 
showVerifierSetting()240     private boolean showVerifierSetting() {
241         return Settings.Global.getInt(getContentResolver(),
242                 Settings.Global.PACKAGE_VERIFIER_SETTING_VISIBLE, 1) > 0;
243     }
244 
245 }
246