Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2012 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 android.uidisolation.cts;
     18 
     19 import android.app.Service;
     20 import android.content.Intent;
     21 import android.os.AsyncTask;
     22 import android.os.Handler;
     23 import android.os.IBinder;
     24 import android.os.Message;
     25 import android.os.Messenger;
     26 import android.os.RemoteException;
     27 import android.util.Log;
     28 import android.webkit.cts.CtsTestServer;
     29 
     30 import java.io.File;
     31 import java.io.FileInputStream;
     32 import java.io.FileNotFoundException;
     33 import java.io.FileOutputStream;
     34 import java.io.InputStream;
     35 import java.io.IOException;
     36 import java.net.MalformedURLException;
     37 import java.net.URL;
     38 
     39 public class PermissionTestService extends Service {
     40     private static String TAG = PermissionTestService.class.getName();
     41 
     42     static final String FILE_NAME = "test_file";
     43 
     44     // Message receieved from the client.
     45     static final int MSG_START_TEST = 1;
     46 
     47     // Messages sent to the client.
     48     static final int MSG_NOTIFY_TEST_SUCCESS = 2;
     49     static final int MSG_NOTIFY_TEST_FAILURE = 3;
     50 
     51     // The different tests types we run.
     52     static final int FILE_READ_TEST = 1;
     53     static final int FILE_WRITE_TEST = 2;
     54     static final int NETWORK_ACCESS_TEST = 3;
     55 
     56     private Messenger mClient;
     57 
     58     // Whether we expect to have permissions to access files, network...
     59     boolean mExpectPermissionsAllowed = true;
     60 
     61     class IncomingHandler extends Handler {
     62         private PermissionTestService mService;
     63 
     64         IncomingHandler(PermissionTestService service) {
     65             mService = service;
     66         }
     67 
     68         @Override
     69         public void handleMessage(Message msg) {
     70             if (msg.what != MSG_START_TEST) {
     71                 Log.e(TAG, "PermissionTestService received bad message: " + msg.what);
     72                 super.handleMessage(msg);
     73                 return;
     74             }
     75             mService.mClient = msg.replyTo;
     76             mService.startTests();
     77         }
     78     }
     79 
     80     final Messenger mMessenger = new Messenger(new IncomingHandler(this));
     81 
     82     class NetworkTestAsyncTask extends AsyncTask<Void, Void, Boolean> {
     83         protected Boolean doInBackground(Void... nothing) {
     84             // Instant apps cannot open TCP sockets
     85             return getPackageManager().isInstantApp() || testNetworkAccess();
     86         }
     87 
     88         protected void onPostExecute(Boolean success) {
     89             testNetworkAccessDone(success);
     90         }
     91     }
     92 
     93     public PermissionTestService() {
     94         this(true);
     95     }
     96 
     97     protected PermissionTestService(boolean expectPermissionsAllowed) {
     98         mExpectPermissionsAllowed = expectPermissionsAllowed;
     99     }
    100 
    101     @Override
    102     public IBinder onBind(Intent intent) {
    103         return mMessenger.getBinder();
    104     }
    105 
    106     private void notifyClientOfFailure(int failingTest) {
    107         try {
    108             mClient.send(Message.obtain(null, MSG_NOTIFY_TEST_FAILURE, failingTest, 0, null));
    109         } catch (RemoteException e) {
    110             Log.e(TAG, "Failed to send message back to client.");
    111         }
    112     }
    113 
    114     private void notifyClientOfSuccess() {
    115         try {
    116             mClient.send(Message.obtain(null, MSG_NOTIFY_TEST_SUCCESS));
    117         } catch (RemoteException e) {
    118             Log.e(TAG, "Failed to send message back to client.");
    119         }
    120     }
    121 
    122     private void startTests() {
    123         if (testFileReadAccess() != mExpectPermissionsAllowed) {
    124             notifyClientOfFailure(FILE_READ_TEST);
    125             return;
    126         }
    127         if (testFileWriteAccess() != mExpectPermissionsAllowed) {
    128             notifyClientOfFailure(FILE_WRITE_TEST);
    129             return;
    130         }
    131 
    132         // testNetworkAccess is performed asynchronously and calls testNetworkAccessDone.
    133         new NetworkTestAsyncTask().execute();
    134     }
    135 
    136     private void testNetworkAccessDone(boolean success) {
    137         // Instant apps cannot open TCP sockets.
    138         if (!getPackageManager().isInstantApp() && success != mExpectPermissionsAllowed) {
    139             notifyClientOfFailure(NETWORK_ACCESS_TEST);
    140             return;
    141         }
    142         notifyClientOfSuccess();
    143     }
    144 
    145     private boolean testFileReadAccess() {
    146         File f = getApplication().getFileStreamPath(FILE_NAME);
    147         if (!f.exists()) {
    148             Log.e(TAG, "testFileReadAccess: test file does not exists.");
    149             return false;
    150         }
    151         if (!f.canRead()) {
    152             Log.e(TAG, "testFileReadAccess: no permission to read test file.");
    153             return false;
    154         }
    155 
    156         FileInputStream fis = null;
    157         try {
    158             fis = new FileInputStream(f);
    159             for (int i = 0; i < 10; i++) {
    160                 int value;
    161                 try {
    162                     value = fis.read();
    163                 } catch (IOException ioe) {
    164                     Log.e(TAG, "testFileReadAccess: failed to read test file, IOException.");
    165                     return false;
    166                 }
    167                 if (value == -1) {
    168                     Log.e(TAG, "testFileReadAccess: failed to read test file.");
    169                     return false;
    170                 }
    171                 if (value != i) {
    172                     Log.e(TAG, "testFileReadAccess: wrong data read from test file.");
    173                     return false;
    174                 }
    175             }
    176         } catch (FileNotFoundException fnfe) {
    177             Log.e(TAG, "testFileReadAccess: failed to read test file, FileNotFoundException.");
    178             return false;
    179         } finally {
    180             if (fis != null) {
    181                 try {
    182                     fis.close();
    183                 } catch (IOException ioe) {
    184                 }
    185             }
    186         }
    187     return true;
    188 }
    189 
    190     private boolean testFileWriteAccess() {
    191         FileOutputStream fos = null;
    192         try {
    193             fos = getApplication().openFileOutput("writeable_file", 0);
    194             byte[] content = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    195             fos.write(content, 0, content.length);
    196         } catch (FileNotFoundException fnfe) {
    197             Log.e(TAG, "Failed to open writable file.");
    198             return false;
    199         } catch (IOException ioe) {
    200             Log.e(TAG, "Failed to write to writable file.");
    201             return false;
    202         } finally {
    203             if (fos != null) {
    204                 try {
    205                     fos.close();
    206                 } catch (IOException ioe) {
    207                 }
    208             }
    209         }
    210         return true;
    211     }
    212 
    213     private boolean testNetworkAccess() {
    214         CtsTestServer webServer = null;
    215         try {
    216             try {
    217                 webServer = new CtsTestServer(getApplication(),
    218                         CtsTestServer.SslMode.TRUST_ANY_CLIENT);
    219             } catch (Exception e) {
    220                 Log.e(TAG, "Failed to create CtsTestServer.");
    221                 return false;
    222             }
    223 
    224             URL url;
    225             try {
    226                 url = new URL(webServer.getAssetUrl("hello.html"));
    227             } catch (MalformedURLException mue) {
    228                 Log.e(TAG, "Test is bad, could not create the URL in "
    229                         + "PermissionTestService.testNetworkAccess().");
    230                 return false;
    231             }
    232             InputStream is = null;
    233             try {
    234                 is = url.openStream();
    235                 // Attempt to read some bytes.
    236                 for (int i = 0; i < 10; i++) {
    237                     int value = is.read();
    238                     if (value == -1) {
    239                         Log.e(TAG, "Failed to read byte " + i + " from network connection");
    240                         return false;
    241                     }
    242                 }
    243             } catch (IOException ioe) {
    244                 Log.e(TAG, "Failed to read from network connection: " + ioe);
    245                 return false;
    246             } catch (SecurityException se) {
    247                 Log.e(TAG, "Failed to read from network connection: " + se);
    248                 return false;
    249             } finally {
    250                 if (is != null) {
    251                     try {
    252                         is.close();
    253                     } catch (IOException ioe) {
    254                     }
    255                 }
    256             }
    257             Log.i(TAG, "Successfully accessed network.");
    258             return true;
    259         } finally {
    260             if (webServer != null) {
    261                 webServer.shutdown();
    262             }
    263         }
    264     }
    265 }
    266