1 /*
2  * Copyright (C) 2016 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.cts.verifier.managedprovisioning;
18 
19 import android.content.Intent;
20 import android.content.pm.PackageManager;
21 import android.database.DataSetObserver;
22 import android.os.Bundle;
23 import android.provider.Settings;
24 import android.util.Log;
25 import android.util.Pair;
26 import android.view.View;
27 
28 import com.android.cts.verifier.ArrayTestListAdapter;
29 import com.android.cts.verifier.PassFailButtons;
30 import com.android.cts.verifier.R;
31 import com.android.cts.verifier.TestListAdapter.TestListItem;
32 import com.android.cts.verifier.features.FeatureUtil;
33 
34 import java.util.Arrays;
35 import java.util.List;
36 
37 /**
38  * Test class to verify transparency for policies enforced by device/profile owner.
39  */
40 public final class PolicyTransparencyTestListActivity extends PassFailButtons.TestListActivity
41         implements View.OnClickListener {
42 
43     private static final String TAG = PolicyTransparencyTestListActivity.class.getSimpleName();
44 
45     public static final String ACTION_CHECK_POLICY_TRANSPARENCY =
46             "com.android.cts.verifier.managedprovisioning.action.CHECK_POLICY_TRANSPARENCY";
47 
48     public static final String EXTRA_MODE =
49             "com.android.cts.verifier.managedprovisioning.extra.mode";
50 
51     public static final int MODE_DEVICE_OWNER = 1;
52     public static final int MODE_MANAGED_PROFILE = 2;
53     public static final int MODE_MANAGED_USER = 4;
54 
55     /**
56      * Pairs of:
57      * <ul>
58      *   <li>An intent to start {@link PolicyTransparencyTestActivity}
59      *   <li>a label to show the user.
60      * </ul>
61      * These contain all the policies except for the user restriction ones.
62      */
63     private static final Pair<Intent, Integer>[] POLICIES;
64     static {
65         final String[] policyTests = new String[] {
66             PolicyTransparencyTestActivity.TEST_CHECK_AUTO_TIME_REQUIRED,
67             PolicyTransparencyTestActivity.TEST_CHECK_KEYGURAD_UNREDACTED_NOTIFICATION,
68             PolicyTransparencyTestActivity.TEST_CHECK_LOCK_SCREEN_INFO,
69             PolicyTransparencyTestActivity.TEST_CHECK_MAXIMUM_TIME_TO_LOCK,
70             PolicyTransparencyTestActivity.TEST_CHECK_PERMITTED_ACCESSIBILITY_SERVICE,
71             PolicyTransparencyTestActivity.TEST_CHECK_PERMITTED_INPUT_METHOD
72         };
73         final String[] settingsIntentActions = new String[] {
74             Settings.ACTION_DATE_SETTINGS,
75             Settings.ACTION_SETTINGS,
76             Settings.ACTION_DISPLAY_SETTINGS,
77             Settings.ACTION_DISPLAY_SETTINGS,
78             Settings.ACTION_ACCESSIBILITY_SETTINGS,
79             Settings.ACTION_SETTINGS
80         };
81         final int[] policyLabels = new int[] {
82             R.string.set_auto_time_required,
83             R.string.disallow_keyguard_unredacted_notifications,
84             R.string.set_lock_screen_info,
85             R.string.set_maximum_time_to_lock,
86             R.string.set_permitted_accessibility_services,
87             R.string.set_permitted_input_methods
88         };
89         if (policyTests.length != settingsIntentActions.length ||
90                 policyTests.length != policyLabels.length) {
91             throw new AssertionError("Number of items in policyTests, "
92                     + " settingsIntentActions and policyLabels do not match");
93         }
94         POLICIES = new Pair[policyTests.length];
95         for (int i = 0; i < policyTests.length; ++i) {
96             final Intent intent =
97                     new Intent(PolicyTransparencyTestActivity.ACTION_SHOW_POLICY_TRANSPARENCY_TEST)
98                             .putExtra(PolicyTransparencyTestActivity.EXTRA_TEST, policyTests[i])
99                             .putExtra(PolicyTransparencyTestActivity.EXTRA_SETTINGS_INTENT_ACTION,
100                                     settingsIntentActions[i]);
101             POLICIES[i] = Pair.create(intent, policyLabels[i]);
102         }
103     }
104 
105     private static final List<String> ALSO_VALID_FOR_MANAGED_PROFILE = Arrays.asList(
106             PolicyTransparencyTestActivity.TEST_CHECK_PERMITTED_ACCESSIBILITY_SERVICE,
107             PolicyTransparencyTestActivity.TEST_CHECK_PERMITTED_INPUT_METHOD);
108     private static final List<String> ALSO_VALID_FOR_MANAGED_USER = Arrays.asList(
109             PolicyTransparencyTestActivity.TEST_CHECK_PERMITTED_ACCESSIBILITY_SERVICE,
110             PolicyTransparencyTestActivity.TEST_CHECK_PERMITTED_INPUT_METHOD);
111 
112     private int mMode;
113 
114     @Override
onCreate(Bundle savedInstanceState)115     protected void onCreate(Bundle savedInstanceState) {
116         super.onCreate(savedInstanceState);
117         setContentView(R.layout.policy_transparency_test_list);
118         setInfoResources(R.string.device_profile_owner_policy_transparency_test,
119                 R.string.device_profile_owner_policy_transparency_test_info, 0);
120         setPassFailButtonClickListeners();
121         setSupportMsgButtonClickListeners();
122 
123         if (!getIntent().hasExtra(EXTRA_MODE)) {
124             throw new RuntimeException("PolicyTransparencyTestListActivity started without extra "
125                     + EXTRA_MODE);
126         }
127         mMode = getIntent().getIntExtra(EXTRA_MODE, MODE_DEVICE_OWNER);
128 
129         Log.d(TAG, "onCreate(): mode=" + mMode);
130 
131         if (mMode != MODE_DEVICE_OWNER && mMode != MODE_MANAGED_PROFILE
132                 && mMode != MODE_MANAGED_USER) {
133             throw new RuntimeException("Unknown mode " + mMode);
134         }
135 
136         final ArrayTestListAdapter adapter = new ArrayTestListAdapter(this);
137         addTestsToAdapter(adapter);
138         adapter.registerDataSetObserver(new DataSetObserver() {
139             @Override
140             public void onChanged() {
141                 updatePassButton();
142             }
143         });
144 
145         setTestListAdapter(adapter);
146     }
147 
addTestsToAdapter(final ArrayTestListAdapter adapter)148     private void addTestsToAdapter(final ArrayTestListAdapter adapter) {
149         for (String restriction :
150                 UserRestrictions.getUserRestrictionsForPolicyTransparency(mMode)) {
151             Intent intent =
152                     UserRestrictions.getUserRestrictionTestIntent(this, restriction, mMode);
153             if (!UserRestrictions.isRestrictionValid(this, restriction)) {
154                 continue;
155             }
156             String title = UserRestrictions.getRestrictionLabel(this, restriction);
157             String testId = getTestId(title);
158             intent.putExtra(PolicyTransparencyTestActivity.EXTRA_TEST_ID, testId);
159             adapter.add(TestListItem.newTest(title, testId, intent, null));
160         }
161         for (Pair<Intent, Integer> policy : POLICIES) {
162             Intent intent = policy.first;
163             String test = intent.getStringExtra(PolicyTransparencyTestActivity.EXTRA_TEST);
164             Log.d(TAG, "addTestsToAdapter(): policy=" + policy + ", mode=" + mMode
165                     + ", test=" + test);
166             if (!isPolicyValid(test)) {
167                 continue;
168             }
169 
170             if (mMode == MODE_MANAGED_PROFILE && !ALSO_VALID_FOR_MANAGED_PROFILE.contains(test)) {
171                 Log.d(TAG, "addTestsToAdapter(): skipping " + test + " on managed profile");
172                 continue;
173             }
174             if (mMode == MODE_MANAGED_USER && !ALSO_VALID_FOR_MANAGED_USER.contains(test)) {
175                 Log.d(TAG, "addTestsToAdapter(): skipping " + test + " on managed user");
176                 continue;
177             }
178             String title = getString(policy.second);
179             String testId = getTestId(title);
180             intent.putExtra(PolicyTransparencyTestActivity.EXTRA_TITLE, title);
181             intent.putExtra(PolicyTransparencyTestActivity.EXTRA_TEST_ID, testId);
182             // This restriction is set per user so current user's DPM should be used instead of
183             // device owner's DPM.
184             if (mMode == MODE_DEVICE_OWNER || ALSO_VALID_FOR_MANAGED_USER.contains(test)) {
185                 intent.putExtra(CommandReceiverActivity.EXTRA_USE_CURRENT_USER_DPM, true);
186             }
187             adapter.add(TestListItem.newTest(title, testId, intent, null));
188         }
189     }
190 
getTestId(String title)191     private String getTestId(String title) {
192         if (mMode == MODE_DEVICE_OWNER) {
193             return "DO_" + title;
194         } else if (mMode == MODE_MANAGED_PROFILE) {
195             return "MP_" + title;
196         } else if (mMode == MODE_MANAGED_USER) {
197             return "MU_" + title;
198         }
199         throw new RuntimeException("Unknown mode " + mMode);
200     }
201 
isPolicyValid(String test)202     private boolean isPolicyValid(String test) {
203         final PackageManager pm = getPackageManager();
204         switch (test) {
205             case PolicyTransparencyTestActivity.TEST_CHECK_PERMITTED_INPUT_METHOD:
206                 return pm.hasSystemFeature(PackageManager.FEATURE_INPUT_METHODS);
207             case PolicyTransparencyTestActivity.TEST_CHECK_PERMITTED_ACCESSIBILITY_SERVICE:
208                 return (pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)
209                         && FeatureUtil.isThirdPartyAccessibilityServiceSupported(this));
210             case PolicyTransparencyTestActivity.TEST_CHECK_KEYGURAD_UNREDACTED_NOTIFICATION:
211             case PolicyTransparencyTestActivity.TEST_CHECK_LOCK_SCREEN_INFO:
212             case PolicyTransparencyTestActivity.TEST_CHECK_MAXIMUM_TIME_TO_LOCK:
213                 return (pm.hasSystemFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN)
214                         && FeatureUtil.isConfigLockScreenSupported(this));
215             default:
216                 return true;
217         }
218     }
219 
setSupportMsgButtonClickListeners()220     private void setSupportMsgButtonClickListeners() {
221         findViewById(R.id.short_msg_button).setOnClickListener(this);
222     }
223 
224     @Override
onClick(View view)225     public void onClick(View view) {
226         if (view.getId() == R.id.short_msg_button) {
227             final Intent intent = new Intent(SetSupportMessageActivity.ACTION_SET_SUPPORT_MSG);
228             intent.putExtra(SetSupportMessageActivity.EXTRA_SUPPORT_MSG_TYPE,
229                     SetSupportMessageActivity.TYPE_SHORT_MSG);
230             startActivity(intent);
231         }
232     }
233 
234     @Override
getTestId()235     public String getTestId() {
236         return getIntent().getStringExtra(PolicyTransparencyTestActivity.EXTRA_TEST_ID);
237     }
238 
239     @Override
finish()240     public void finish() {
241         super.finish();
242         final Intent intent = new Intent(CommandReceiverActivity.ACTION_EXECUTE_COMMAND);
243         intent.putExtra(CommandReceiverActivity.EXTRA_COMMAND,
244                 CommandReceiverActivity.COMMAND_CLEAR_POLICIES);
245         intent.putExtra(CommandReceiverActivity.EXTRA_USE_CURRENT_USER_DPM, true);
246         intent.putExtra(PolicyTransparencyTestListActivity.EXTRA_MODE, mMode);
247         Log.d(TAG, "finish(): starting activity using " + intent);
248         startActivity(intent);
249     }
250 }
251