1 /* 2 * Copyright (C) 2010 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; 18 19 import android.app.AlertDialog; 20 import android.app.ListActivity; 21 import android.content.DialogInterface; 22 import android.content.SharedPreferences; 23 import android.content.pm.PackageInfo; 24 import android.content.pm.PackageManager; 25 import android.content.pm.PackageManager.NameNotFoundException; 26 import android.content.pm.PermissionInfo; 27 import android.os.Bundle; 28 import android.util.Log; 29 import android.view.Menu; 30 import android.view.MenuInflater; 31 import android.view.MenuItem; 32 import android.view.View; 33 import android.view.Window; 34 import android.widget.CompoundButton; 35 import android.widget.Switch; 36 import android.widget.Toast; 37 38 /** Top-level {@link ListActivity} for launching tests and managing results. */ 39 public class TestListActivity extends AbstractTestListActivity implements View.OnClickListener { 40 private static final int CTS_VERIFIER_PERMISSION_REQUEST = 1; 41 42 private static final String TAG = TestListActivity.class.getSimpleName(); 43 // Records the current display mode. 44 // Default is unfolded mode, and it will be changed when clicking the switch button. 45 public static String sCurrentDisplayMode = DisplayMode.UNFOLDED.toString(); 46 // Flag of launch app to fetch the unfolded/folded tests in main view from AndroidManifest.xml. 47 protected static boolean sInitialLaunch; 48 49 // Enumerates the display modes, including unfolded and folded. 50 protected enum DisplayMode { 51 UNFOLDED, FOLDED; 52 53 @Override toString()54 public String toString() { 55 return name().toLowerCase(); 56 } 57 58 /** 59 * Coverts the mode as suffix with brackets for test name. 60 * 61 * @return A string containing mode with brackets for folded mode; 62 * empty string for unfolded mode. 63 */ asSuffix()64 public String asSuffix() { 65 if (name().equals(FOLDED.name())) { 66 return String.format("[%s]", toString()); 67 } 68 return ""; 69 } 70 } 71 72 @Override onClick(View v)73 public void onClick (View v) { 74 handleMenuItemSelected(v.getId()); 75 } 76 77 @Override onCreate(Bundle savedInstanceState)78 protected void onCreate(Bundle savedInstanceState) { 79 super.onCreate(savedInstanceState); 80 81 try { 82 PackageManager pm = getPackageManager(); 83 PackageInfo packageInfo = pm.getPackageInfo( 84 getApplicationInfo().packageName, PackageManager.GET_PERMISSIONS); 85 86 if (packageInfo.requestedPermissions != null) { 87 for (String permission : packageInfo.requestedPermissions) { 88 Log.v(TAG, "Checking permissions for: " + permission); 89 try { 90 PermissionInfo info = pm.getPermissionInfo(permission, 0); 91 if ((info.protectionLevel & PermissionInfo.PROTECTION_DANGEROUS) == 0) { 92 continue; 93 } 94 } catch (NameNotFoundException e) { 95 Log.v(TAG, "Checking permissions for: " + permission + "not found"); 96 continue; 97 } 98 if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { 99 requestPermissions(packageInfo.requestedPermissions, 100 CTS_VERIFIER_PERMISSION_REQUEST); 101 /* don't return here. Some tests (i.e. USB Restrict Access test) 102 * which need to run even if permissions are incomplete. 103 */ 104 } 105 } 106 } 107 createContinue(); 108 } catch (NameNotFoundException e) { 109 Log.e(TAG, "Unable to load package's permissions", e); 110 Toast.makeText(this, R.string.runtime_permissions_error, Toast.LENGTH_SHORT).show(); 111 } 112 } 113 createContinue()114 private void createContinue() { 115 if (!isTaskRoot()) { 116 finish(); 117 } 118 sInitialLaunch = true; 119 120 setTitle(getString(R.string.title_version, Version.getVersionName(this))); 121 122 if (!getWindow().hasFeature(Window.FEATURE_ACTION_BAR)) { 123 View footer = getLayoutInflater().inflate(R.layout.test_list_footer, null); 124 125 footer.findViewById(R.id.clear).setOnClickListener(this); 126 footer.findViewById(R.id.export).setOnClickListener(this); 127 128 getListView().addFooterView(footer); 129 } 130 131 setTestListAdapter(new ManifestTestListAdapter(this, null)); 132 } 133 134 @Override onRequestPermissionsResult( int requestCode, String permissions[], int[] grantResults)135 public void onRequestPermissionsResult( 136 int requestCode, String permissions[], int[] grantResults) { 137 if (requestCode == CTS_VERIFIER_PERMISSION_REQUEST) { 138 if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 139 createContinue(); 140 return; 141 } 142 Log.v(TAG, "Permission not granted."); 143 Toast.makeText(this, R.string.runtime_permissions_error, Toast.LENGTH_SHORT).show(); 144 } 145 } 146 147 @Override onCreateOptionsMenu(Menu menu)148 public boolean onCreateOptionsMenu(Menu menu) { 149 MenuInflater inflater = getMenuInflater(); 150 inflater.inflate(R.menu.test_list_menu, menu); 151 152 // Switch button for unfolded and folded tests. 153 MenuItem item = (MenuItem) menu.findItem(R.id.switch_item); 154 item.setActionView(R.layout.display_mode_switch); 155 Switch displayModeSwitch = item.getActionView().findViewById(R.id.switch_button); 156 157 // Restores the original display mode when launching the app after killing the process. 158 // Otherwise, gets the current display mode to show switch status. 159 boolean isFoldedMode; 160 if (sInitialLaunch) { 161 isFoldedMode = getCurrentDisplayMode().equals(DisplayMode.FOLDED.toString()); 162 } else { 163 isFoldedMode = sCurrentDisplayMode.equals(DisplayMode.FOLDED.toString()); 164 } 165 displayModeSwitch.setChecked(isFoldedMode); 166 167 displayModeSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 168 @Override 169 public void onCheckedChanged(CompoundButton buttonView, 170 boolean isChecked) { 171 if (isChecked) { 172 sCurrentDisplayMode = DisplayMode.FOLDED.toString(); 173 } else { 174 sCurrentDisplayMode = DisplayMode.UNFOLDED.toString(); 175 } 176 handleSwitchItemSelected(); 177 } 178 }); 179 return true; 180 } 181 182 @Override onOptionsItemSelected(MenuItem item)183 public boolean onOptionsItemSelected(MenuItem item) { 184 return handleMenuItemSelected(item.getItemId()) ? true : super.onOptionsItemSelected(item); 185 } 186 handleClearItemSelected()187 private void handleClearItemSelected() { 188 new AlertDialog.Builder(this) 189 .setMessage(R.string.test_results_clear_title) 190 .setPositiveButton(R.string.test_results_clear_yes, 191 new DialogInterface.OnClickListener() { 192 public void onClick(DialogInterface dialog, int id) { 193 mAdapter.clearTestResults(); 194 Toast.makeText( 195 TestListActivity.this, 196 R.string.test_results_cleared, 197 Toast.LENGTH_SHORT) 198 .show(); 199 } 200 }) 201 .setNegativeButton(R.string.test_results_clear_cancel, null) 202 .show(); 203 } 204 handleExportItemSelected()205 private void handleExportItemSelected() { 206 new ReportExporter(this, mAdapter).execute(); 207 } 208 209 // Sets up the flags after switching display mode and reloads tests on UI. handleSwitchItemSelected()210 private void handleSwitchItemSelected() { 211 setCurrentDisplayMode(sCurrentDisplayMode); 212 mAdapter.loadTestResults(); 213 } 214 handleMenuItemSelected(int id)215 private boolean handleMenuItemSelected(int id) { 216 if (id == R.id.clear) { 217 handleClearItemSelected(); 218 } else if (id == R.id.export) { 219 handleExportItemSelected(); 220 } else { 221 return false; 222 } 223 224 return true; 225 } 226 227 /** 228 * Sets current display mode to sharedpreferences. 229 * 230 * @param mode A string of current display mode. 231 */ setCurrentDisplayMode(String mode)232 private void setCurrentDisplayMode(String mode) { 233 SharedPreferences pref = getSharedPreferences(DisplayMode.class.getName(), MODE_PRIVATE); 234 pref.edit().putString(DisplayMode.class.getName(), mode).commit(); 235 } 236 237 /** 238 * Gets current display mode from sharedpreferences. 239 * 240 * @return A string of current display mode. 241 */ getCurrentDisplayMode()242 private String getCurrentDisplayMode() { 243 String mode = getSharedPreferences(DisplayMode.class.getName(), MODE_PRIVATE) 244 .getString(DisplayMode.class.getName(), ""); 245 return mode; 246 } 247 }