Home | History | Annotate | Download | only in location
      1 /*
      2  * Copyright (C) 2013 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.location;
     18 
     19 import android.content.ContentResolver;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.location.LocationManager;
     23 import android.os.Bundle;
     24 import android.provider.Settings;
     25 import android.provider.Settings.Secure;
     26 import android.view.LayoutInflater;
     27 import android.view.View;
     28 import android.view.ViewGroup;
     29 import android.widget.ImageView;
     30 import android.widget.TextView;
     31 import com.android.cts.verifier.PassFailButtons;
     32 import com.android.cts.verifier.R;
     33 
     34 /**
     35  * Asks the user to put the device in one of the four location modes and then checks to see if
     36  * {@link Secure#isLocationProviderEnabled(ContentResolver, String)} and {@link
     37  * LocationManager#isProviderEnabled(String)} have the expected values for GPS and Wi-Fi. For
     38  * example in battery saving mode, Wi-Fi should be on but GPS should be off.
     39  *
     40  * It would be hard to automate these tests because the {@link Secure#LOCATION_MODE} API is only
     41  * accessible to apps in the system image. Furthermore, selecting two of the modes requires the user
     42  * to accept the NLP confirmation dialog.
     43  */
     44 public abstract class LocationModeTestActivity
     45         extends PassFailButtons.Activity implements Runnable {
     46 
     47     private static final String STATE = "state";
     48     protected static final int PASS = 1;
     49     protected static final int FAIL = 2;
     50     protected static final int WAIT_FOR_USER = 3;
     51 
     52     protected int mState;
     53     protected int[] mStatus;
     54     private LayoutInflater mInflater;
     55     private ViewGroup mItemList;
     56     private Runnable mRunner;
     57     private View mHandler;
     58 
     59     @Override
     60     protected void onCreate(Bundle savedInstanceState) {
     61         super.onCreate(savedInstanceState);
     62 
     63         if (savedInstanceState != null) {
     64             mState = savedInstanceState.getInt(STATE, 0);
     65         }
     66 
     67         mRunner = this;
     68         mInflater = getLayoutInflater();
     69         View view = mInflater.inflate(R.layout.location_mode_main, null);
     70         mItemList = (ViewGroup) view.findViewById(R.id.test_items);
     71         mHandler = mItemList;
     72 
     73         createTestItems();
     74         mStatus = new int[mItemList.getChildCount()];
     75         setContentView(view);
     76 
     77         setPassFailButtonClickListeners();
     78 
     79         setInfoResources();
     80 
     81         getPassButton().setEnabled(false);
     82     }
     83 
     84     @Override
     85     protected void onSaveInstanceState(Bundle outState) {
     86         outState.putInt(STATE, mState);
     87     }
     88 
     89     @Override
     90     protected void onResume() {
     91         super.onResume();
     92         next();
     93     }
     94 
     95     /**
     96      * Template method used by the subclass to create the checks corresponding to each value of
     97      * {@link #mState}. Subclass should call {@link #createUserItem(int)} and {@link
     98      * #createAutoItem(int)} as appropriate to generate each item.
     99      */
    100     protected abstract void createTestItems();
    101 
    102     /**
    103      * Template method used by the subclass to call {@link #setInfoResources(int, int, int)} with
    104      * the appropriate resources.
    105      */
    106     protected abstract void setInfoResources();
    107 
    108     /**
    109      * Subclass can call this to create a test step where the user must perform some action such
    110      * as setting the location mode.
    111      */
    112     protected View createUserItem(int stringId) {
    113         View item = mInflater.inflate(R.layout.location_mode_item, mItemList, false);
    114         TextView instructions = (TextView) item.findViewById(R.id.instructions);
    115         instructions.setText(stringId);
    116         mItemList.addView(item);
    117         return item;
    118     }
    119 
    120     /**
    121      * Subclass can call this to create a test step where the test automatically evaluates whether
    122      * an expected condition is satisfied, such as GPS is off.
    123      */
    124     protected View createAutoItem(int stringId) {
    125         View item = mInflater.inflate(R.layout.location_mode_item, mItemList, false);
    126         TextView instructions = (TextView) item.findViewById(R.id.instructions);
    127         instructions.setText(stringId);
    128         View button = item.findViewById(R.id.launch_settings);
    129         button.setVisibility(View.GONE);
    130         mItemList.addView(item);
    131         return item;
    132     }
    133 
    134     /**
    135      * Set the visible state of a test item to passed or failed.
    136      */
    137     private void setItemState(int index, boolean passed) {
    138         ViewGroup item = (ViewGroup) mItemList.getChildAt(index);
    139         ImageView status = (ImageView) item.findViewById(R.id.status);
    140         status.setImageResource(passed ? R.drawable.fs_good : R.drawable.fs_error);
    141         View button = item.findViewById(R.id.launch_settings);
    142         button.setClickable(false);
    143         button.setEnabled(false);
    144         status.invalidate();
    145     }
    146 
    147     /**
    148      * Set the visible state of a test item to waiting.
    149      */
    150     protected void markItemWaiting(int index) {
    151         ViewGroup item = (ViewGroup) mItemList.getChildAt(index);
    152         ImageView status = (ImageView) item.findViewById(R.id.status);
    153         status.setImageResource(R.drawable.fs_warning);
    154         status.invalidate();
    155     }
    156 
    157     /**
    158      * Advances the state machine.
    159      */
    160     public void run() {
    161         // Advance test state until we find case where it hasn't passed (yet)
    162         while (mState < mStatus.length && mStatus[mState] != WAIT_FOR_USER) {
    163             if (mStatus[mState] == PASS) {
    164                 setItemState(mState, true);
    165                 mState++;
    166             } else if (mStatus[mState] == FAIL) {
    167                 setItemState(mState, false);
    168                 return;
    169             } else {
    170                 break;
    171             }
    172         }
    173 
    174         if (mState < mStatus.length && mStatus[mState] == WAIT_FOR_USER) {
    175             markItemWaiting(mState);
    176         }
    177 
    178         testAdvance(mState);
    179 
    180         if (mState == mStatus.length - 1 && mStatus[mState] == PASS) {
    181             // All tests run and pass
    182             getPassButton().setEnabled(true);
    183         }
    184     }
    185 
    186     /**
    187      * Launches Locations &gt; Settings so the user can set the location mode. Public because it
    188      * is referenced by layout.
    189      */
    190     public void launchSettings(View button) {
    191         startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
    192     }
    193 
    194     /**
    195      * Return to the state machine to progress through the tests.
    196      */
    197     protected void next() {
    198         mHandler.post(mRunner);
    199     }
    200 
    201     /**
    202      * Wait for things to settle before returning to the state machine.
    203      */
    204     protected void delay() {
    205         mHandler.postDelayed(mRunner, 2000);
    206     }
    207 
    208     // Tests
    209 
    210     private int getLocationMode() {
    211         ContentResolver cr = getContentResolver();
    212         return Secure.getInt(cr, Secure.LOCATION_MODE, Secure.LOCATION_MODE_OFF);
    213     }
    214 
    215     protected void testIsOn(int i) {
    216         int mode = getLocationMode();
    217         boolean passed = mode != Secure.LOCATION_MODE_OFF;
    218         if (passed) {
    219             mStatus[i] = PASS;
    220         } else {
    221             mStatus[i] = WAIT_FOR_USER;
    222         }
    223         next();
    224     }
    225 
    226     protected void testIsExpectedMode(int i, int expectedMode) {
    227         int mode = getLocationMode();
    228         boolean passed = mode == expectedMode;
    229         if (passed) {
    230             mStatus[i] = PASS;
    231             next();
    232         } else {
    233             mStatus[i] = WAIT_FOR_USER;
    234             delay();
    235         }
    236     }
    237 
    238     protected void testSecureProviderIsEnabled(int i, String provider) {
    239         ContentResolver cr = getContentResolver();
    240         boolean enabled = Secure.isLocationProviderEnabled(cr, provider);
    241         mStatus[i] = enabled ? PASS : FAIL;
    242         next();
    243     }
    244 
    245     protected void testSecureProviderIsDisabled(int i, String provider) {
    246         ContentResolver cr = getContentResolver();
    247         boolean enabled = Secure.isLocationProviderEnabled(cr, provider);
    248         mStatus[i] = !enabled ? PASS : FAIL;
    249         next();
    250     }
    251 
    252     protected void testManagerProviderIsEnabled(int i, String gpsProvider) {
    253         LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    254         boolean enabled = manager.isProviderEnabled(gpsProvider);
    255         mStatus[i] = enabled ? PASS : FAIL;
    256         next();
    257     }
    258 
    259     protected void testManagerProviderIsDisabled(int i, String gpsProvider) {
    260         LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    261         boolean enabled = manager.isProviderEnabled(gpsProvider);
    262         mStatus[i] = !enabled ? PASS : FAIL;
    263         next();
    264     }
    265 
    266     protected abstract void testAdvance(int state);
    267 }
    268