1 /*
2  * Copyright (C) 2015 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 static android.os.UserHandle.myUserId;
20 
21 import android.app.admin.DevicePolicyManager;
22 import android.content.ActivityNotFoundException;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.pm.ApplicationInfo;
27 import android.content.pm.PackageManager;
28 import android.net.Uri;
29 import android.os.Bundle;
30 import android.os.UserManager;
31 import android.provider.Settings;
32 import android.util.Log;
33 import android.view.View;
34 import android.view.ViewGroup;
35 import android.widget.Button;
36 import android.widget.ImageView;
37 import android.widget.RadioGroup;
38 import android.widget.TextView;
39 import android.widget.Toast;
40 
41 import com.android.cts.verifier.PassFailButtons;
42 import com.android.cts.verifier.R;
43 
44 import java.util.Arrays;
45 
46 public class PermissionLockdownTestActivity extends PassFailButtons.Activity
47         implements RadioGroup.OnCheckedChangeListener {
48 
49     private static final String TAG = PermissionLockdownTestActivity.class.getSimpleName();
50 
51     private static final String PERMISSION_APP_PACKAGE = "com.android.cts.permissionapp";
52 
53     // Alias used for starting the activity from ByodFlowTestActivity (Managed profile tests).
54     static final String ACTIVITY_ALIAS
55             = "com.android.cts.verifier.managedprovisioning" +
56                     ".ManagedProfilePermissionLockdownTestActivity";
57 
58     private static final String MANAGED_PROVISIONING_ACTION_PREFIX
59             = "com.android.cts.verifier.managedprovisioning.action.";
60     // Indicates that activity is started for device owner case.
61     static final String ACTION_CHECK_PERMISSION_LOCKDOWN
62             = MANAGED_PROVISIONING_ACTION_PREFIX + "CHECK_PERMISSION_LOCKDOWN";
63     // Indicates that activity is started for profile owner case.
64     static final String ACTION_MANAGED_PROFILE_CHECK_PERMISSION_LOCKDOWN
65             = MANAGED_PROVISIONING_ACTION_PREFIX + "MANAGED_PROFILE_CHECK_PERMISSION_LOCKDOWN";
66 
67     // Permission grant states will be set on these permissions.
68     private static final String[] CONTACTS_PERMISSIONS = new String[] {
69             android.Manifest.permission.READ_CONTACTS, android.Manifest.permission.WRITE_CONTACTS
70     };
71 
72     private boolean mDeviceOwnerTest;
73     private DevicePolicyManager mDevicePolicyManager;
74     private ComponentName mAdmin;
75 
76     @Override
onCreate(Bundle savedInstanceState)77     public void onCreate(Bundle savedInstanceState) {
78         super.onCreate(savedInstanceState);
79         setContentView(R.layout.permission_lockdown);
80 
81         Log.d(TAG, "created on user " + myUserId());
82 
83         mDevicePolicyManager =
84                 (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
85         mAdmin = DeviceAdminTestReceiver.getReceiverComponentName();
86 
87         mDeviceOwnerTest =
88                 ACTION_CHECK_PERMISSION_LOCKDOWN.equals(getIntent().getAction()) ? true : false;
89         // Return immediately if we are neither profile nor device owner.
90         if (!isProfileOrDeviceOwner()) {
91             setTestResultAndFinish(false);
92             return;
93         }
94 
95         buildLayout();
96     }
97 
buildLayout()98     private void buildLayout() {
99         PackageManager packageManager = getPackageManager();
100         ApplicationInfo applicationInfo = null;
101         try {
102             // We need to make sure that the CtsPermissionApp is installed on the device or
103             // work profile.
104             applicationInfo = packageManager.getApplicationInfo(
105                     PERMISSION_APP_PACKAGE, 0 /* flags */);
106         } catch (PackageManager.NameNotFoundException e) {
107             showToast(getString(R.string.package_not_found, PERMISSION_APP_PACKAGE));
108             setTestResultAndFinish(false);
109             return;
110         }
111 
112         ImageView packageIconImageView = (ImageView) findViewById(R.id.package_icon);
113         packageIconImageView.setImageDrawable(packageManager.getApplicationIcon(applicationInfo));
114         TextView packageNameTextView = (TextView) findViewById(R.id.package_name);
115         packageNameTextView.setText(packageManager.getApplicationLabel(applicationInfo));
116 
117         TextView permissionNameTextView = (TextView) findViewById(R.id.permission_name);
118         permissionNameTextView.setText(Arrays.toString(CONTACTS_PERMISSIONS));
119 
120         // Get the current permission grant state for initializing the RadioGroup.
121         int readPermissionState = mDevicePolicyManager.getPermissionGrantState(mAdmin,
122                     PERMISSION_APP_PACKAGE, CONTACTS_PERMISSIONS[0]);
123         int writePermissionState = mDevicePolicyManager.getPermissionGrantState(mAdmin,
124                 PERMISSION_APP_PACKAGE, CONTACTS_PERMISSIONS[1]);
125         int currentPermissionState;
126         if (readPermissionState == DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED ||
127         writePermissionState == DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED) {
128             currentPermissionState = DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
129         } else if (readPermissionState == DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED ||
130                     writePermissionState == DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED) {
131             currentPermissionState = DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
132         } else {
133             currentPermissionState = readPermissionState;
134         }
135         RadioGroup permissionRadioGroup = (RadioGroup) findViewById(R.id.permission_group);
136         switch (currentPermissionState) {
137             case DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED: {
138                 permissionRadioGroup.check(R.id.permission_allow);
139             } break;
140             case DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT: {
141                 permissionRadioGroup.check(R.id.permission_default);
142             } break;
143             case  DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED: {
144                 permissionRadioGroup.check(R.id.permission_deny);
145             } break;
146         }
147         permissionRadioGroup.setOnCheckedChangeListener(this);
148 
149         addFinishOrPassFailButtons();
150     }
151 
addFinishOrPassFailButtons()152     private void addFinishOrPassFailButtons() {
153         // In case of device owner, we include the pass-fail buttons where as in case of profile
154         // owner, we add a finish button.
155         ViewGroup parentView = (ViewGroup) findViewById(R.id.permission_lockdown_activity);
156         if (mDeviceOwnerTest) {
157             parentView.addView(
158                     getLayoutInflater().inflate(R.layout.pass_fail_buttons, parentView, false));
159             setInfoResources(R.string.device_profile_owner_permission_lockdown_test,
160                     R.string.device_owner_permission_lockdown_test_info, 0);
161             setPassFailButtonClickListeners();
162         } else {
163             Button finishButton = new Button(this);
164             finishButton.setText(R.string.finish_button_label);
165             finishButton.setOnClickListener(new View.OnClickListener() {
166                 @Override
167                 public void onClick(View v) {
168                     PermissionLockdownTestActivity.this.setTestResultAndFinish(false);
169                 }
170             });
171             parentView.addView(finishButton);
172         }
173     }
174 
175     // Dispatches an intent to open the Settings screen for CtsPermissionApp.
openSettings(View v)176     public void openSettings(View v) {
177         Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
178                 .setData(Uri.fromParts("package", PERMISSION_APP_PACKAGE, null))
179                 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
180         try {
181             startActivity(intent);
182         } catch (ActivityNotFoundException e) {
183             showToast(getString(R.string.activity_not_found, intent));
184         }
185     }
186 
187     @Override
onCheckedChanged(RadioGroup radioGroup, int checkedId)188     public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
189         int permissionGrantState = -1;
190         switch (checkedId) {
191             case R.id.permission_allow: {
192                 permissionGrantState = DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
193             } break;
194             case R.id.permission_default: {
195                 permissionGrantState = DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT;
196             } break;
197             case R.id.permission_deny: {
198                 permissionGrantState = DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
199             } break;
200         }
201         mDevicePolicyManager.setPermissionGrantState(mAdmin, PERMISSION_APP_PACKAGE,
202                 CONTACTS_PERMISSIONS[0], permissionGrantState);
203         mDevicePolicyManager.setPermissionGrantState(mAdmin, PERMISSION_APP_PACKAGE,
204                 CONTACTS_PERMISSIONS[1], permissionGrantState);
205     }
206 
isProfileOrDeviceOwner()207     private boolean isProfileOrDeviceOwner() {
208         String adminPackage = mAdmin.getPackageName();
209         // On headless system user mode, permissions are set in the current user, which is not
210         // device owner, but affiliated profile owner
211         boolean expectDeviceOwner = mDeviceOwnerTest && !UserManager.isHeadlessSystemUserMode();
212 
213         boolean isDeviceOwner = mDevicePolicyManager.isDeviceOwnerApp(adminPackage);
214         boolean isProfileOwner = mDevicePolicyManager.isProfileOwnerApp(adminPackage);
215         Log.d(TAG, "isProfileOrDeviceOwner(): userId=" + myUserId()
216                 + ", mDeviceOwnerTest=" + mDeviceOwnerTest
217                 + ", expectDeviceOwner=" + expectDeviceOwner
218                 + ", isDeviceOwner=" + isDeviceOwner
219                 + ", isProfileOwner=" + isProfileOwner);
220 
221         if (expectDeviceOwner) {
222             if (!isDeviceOwner) {
223                 showToast(getString(R.string.not_device_owner, adminPackage));
224                 return false;
225             }
226             return true;
227         }
228         if (!isProfileOwner) {
229             showToast(getString(R.string.not_profile_owner, adminPackage));
230             return false;
231         }
232         return true;
233     }
234 
showToast(String toast)235     private void showToast(String toast) {
236         Log.d(TAG, "showToast(" + toast + ")");
237         Toast.makeText(this, toast, Toast.LENGTH_LONG).show();
238     }
239 }