Home | History | Annotate | Download | only in activity
      1 /*
      2  * Copyright (C) 2006 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.app.activity;
     18 
     19 import android.content.ComponentName;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.content.ServiceConnection;
     23 import android.os.Binder;
     24 import android.os.Bundle;
     25 import android.os.RemoteException;
     26 import android.os.IBinder;
     27 import android.os.Parcel;
     28 import android.test.suitebuilder.annotation.MediumTest;
     29 import android.test.suitebuilder.annotation.SmallTest;
     30 import android.test.suitebuilder.annotation.Suppress;
     31 import android.util.Log;
     32 
     33 // These test binders purport to support an interface whose canonical
     34 // interface name is ServiceTest.SERVICE_LOCAL
     35 // Temporarily suppress, this test is causing unit test suite run to fail
     36 // TODO: remove this suppress
     37 @Suppress
     38 public class ServiceTest extends ActivityTestsBase {
     39 
     40     public static final String SERVICE_LOCAL =
     41             "com.android.frameworks.coretests.activity.SERVICE_LOCAL";
     42     public static final String SERVICE_LOCAL_GRANTED =
     43             "com.android.frameworks.coretests.activity.SERVICE_LOCAL_GRANTED";
     44     public static final String SERVICE_LOCAL_DENIED =
     45             "com.android.frameworks.coretests.activity.SERVICE_LOCAL_DENIED";
     46 
     47     public static final String REPORT_OBJ_NAME = "report";
     48 
     49     public static final int STARTED_CODE = 1;
     50     public static final int DESTROYED_CODE = 2;
     51     public static final int SET_REPORTER_CODE = 3;
     52     public static final int UNBIND_CODE = 4;
     53     public static final int REBIND_CODE = 5;
     54 
     55     public static final int STATE_START_1 = 0;
     56     public static final int STATE_START_2 = 1;
     57     public static final int STATE_UNBIND = 2;
     58     public static final int STATE_DESTROY = 3;
     59     public static final int STATE_REBIND = 4;
     60     public static final int STATE_UNBIND_ONLY = 5;
     61     public int mStartState;
     62 
     63     public IBinder mStartReceiver = new Binder() {
     64         @Override
     65         protected boolean onTransact(int code, Parcel data, Parcel reply,
     66                 int flags) throws RemoteException {
     67             //Log.i("ServiceTest", "Received code " + code + " in state " + mStartState);
     68             if (code == STARTED_CODE) {
     69                 data.enforceInterface(SERVICE_LOCAL);
     70                 int count = data.readInt();
     71                 if (mStartState == STATE_START_1) {
     72                     if (count == 1) {
     73                         finishGood();
     74                     } else {
     75                         finishBad("onStart() again on an object when it should have been the first time");
     76                     }
     77                 } else if (mStartState == STATE_START_2) {
     78                     if (count == 2) {
     79                         finishGood();
     80                     } else {
     81                         finishBad("onStart() the first time on an object when it should have been the second time");
     82                     }
     83                 } else {
     84                     finishBad("onStart() was called when not expected (state="+mStartState+")");
     85                 }
     86                 return true;
     87             } else if (code == DESTROYED_CODE) {
     88                 data.enforceInterface(SERVICE_LOCAL);
     89                 if (mStartState == STATE_DESTROY) {
     90                     finishGood();
     91                 } else {
     92                     finishBad("onDestroy() was called when not expected (state="+mStartState+")");
     93                 }
     94                 return true;
     95             } else if (code == UNBIND_CODE) {
     96                 data.enforceInterface(SERVICE_LOCAL);
     97                 if (mStartState == STATE_UNBIND) {
     98                     mStartState = STATE_DESTROY;
     99                 } else if (mStartState == STATE_UNBIND_ONLY) {
    100                     finishGood();
    101                 } else {
    102                     finishBad("onUnbind() was called when not expected (state="+mStartState+")");
    103                 }
    104                 return true;
    105             } else if (code == REBIND_CODE) {
    106                 data.enforceInterface(SERVICE_LOCAL);
    107                 if (mStartState == STATE_REBIND) {
    108                     finishGood();
    109                 } else {
    110                     finishBad("onRebind() was called when not expected (state="+mStartState+")");
    111                 }
    112                 return true;
    113             } else {
    114                 return super.onTransact(code, data, reply, flags);
    115             }
    116         }
    117     };
    118 
    119     public class EmptyConnection implements ServiceConnection {
    120         public void onServiceConnected(ComponentName name, IBinder service) {
    121         }
    122 
    123         public void onServiceDisconnected(ComponentName name) {
    124         }
    125     }
    126 
    127     public class TestConnection implements ServiceConnection {
    128         private final boolean mExpectDisconnect;
    129         private final boolean mSetReporter;
    130         private boolean mMonitor;
    131         private int mCount;
    132 
    133         public TestConnection(boolean expectDisconnect, boolean setReporter) {
    134             mExpectDisconnect = expectDisconnect;
    135             mSetReporter = setReporter;
    136             mMonitor = !setReporter;
    137         }
    138 
    139         void setMonitor(boolean v) {
    140             mMonitor = v;
    141         }
    142 
    143         public void onServiceConnected(ComponentName name, IBinder service) {
    144             if (mSetReporter) {
    145                 Parcel data = Parcel.obtain();
    146                 data.writeInterfaceToken(SERVICE_LOCAL);
    147                 data.writeStrongBinder(mStartReceiver);
    148                 try {
    149                     service.transact(SET_REPORTER_CODE, data, null, 0);
    150                 } catch (RemoteException e) {
    151                     finishBad("DeadObjectException when sending reporting object");
    152                 }
    153                 data.recycle();
    154             }
    155 
    156             if (mMonitor) {
    157                 mCount++;
    158                 if (mStartState == STATE_START_1) {
    159                     if (mCount == 1) {
    160                         finishGood();
    161                     } else {
    162                         finishBad("onServiceConnected() again on an object when it should have been the first time");
    163                     }
    164                 } else if (mStartState == STATE_START_2) {
    165                     if (mCount == 2) {
    166                         finishGood();
    167                     } else {
    168                         finishBad("onServiceConnected() the first time on an object when it should have been the second time");
    169                     }
    170                 } else {
    171                     finishBad("onServiceConnected() called unexpectedly");
    172                 }
    173             }
    174         }
    175 
    176         public void onServiceDisconnected(ComponentName name) {
    177             if (mMonitor) {
    178                 if (mStartState == STATE_DESTROY) {
    179                     if (mExpectDisconnect) {
    180                         finishGood();
    181                     } else {
    182                         finishBad("onServiceDisconnected() when it shouldn't have been");
    183                     }
    184                 } else {
    185                     finishBad("onServiceDisconnected() called unexpectedly");
    186                 }
    187             }
    188         }
    189     }
    190 
    191     void startExpectResult(Intent service) {
    192         startExpectResult(service, new Bundle());
    193     }
    194 
    195     void startExpectResult(Intent service, Bundle bundle) {
    196         bundle.putIBinder(REPORT_OBJ_NAME, mStartReceiver);
    197         boolean success = false;
    198         try {
    199             //Log.i("foo", "STATE_START_1");
    200             mStartState = STATE_START_1;
    201             getContext().startService(new Intent(service).putExtras(bundle));
    202             waitForResultOrThrow(5 * 1000, "service to start first time");
    203             //Log.i("foo", "STATE_START_2");
    204             mStartState = STATE_START_2;
    205             getContext().startService(new Intent(service).putExtras(bundle));
    206             waitForResultOrThrow(5 * 1000, "service to start second time");
    207             success = true;
    208         } finally {
    209             if (!success) {
    210                 try {
    211                     getContext().stopService(service);
    212                 } catch (Exception e) {
    213                     // eat
    214                 }
    215             }
    216         }
    217         //Log.i("foo", "STATE_DESTROY");
    218         mStartState = STATE_DESTROY;
    219         getContext().stopService(service);
    220         waitForResultOrThrow(5 * 1000, "service to be destroyed");
    221     }
    222 
    223     void startExpectNoPermission(Intent service) {
    224         try {
    225             getContext().startService(service);
    226             fail("Expected security exception when starting " + service);
    227         } catch (SecurityException e) {
    228             // expected
    229         }
    230     }
    231 
    232     void bindExpectResult(Intent service) {
    233         TestConnection conn = new TestConnection(true, false);
    234         TestConnection conn2 = new TestConnection(false, false);
    235         boolean success = false;
    236         try {
    237             // Expect to see the TestConnection connected.
    238             mStartState = STATE_START_1;
    239             getContext().bindService(service, conn, 0);
    240             getContext().startService(service);
    241             waitForResultOrThrow(5 * 1000, "existing connection to receive service");
    242 
    243             // Expect to see the second TestConnection connected.
    244             getContext().bindService(service, conn2, 0);
    245             waitForResultOrThrow(5 * 1000, "new connection to receive service");
    246 
    247             getContext().unbindService(conn2);
    248             success = true;
    249         } finally {
    250             if (!success) {
    251                 try {
    252                     getContext().stopService(service);
    253                     getContext().unbindService(conn);
    254                     getContext().unbindService(conn2);
    255                 } catch (Exception e) {
    256                     // eat
    257                 }
    258             }
    259         }
    260 
    261         // Expect to see the TestConnection disconnected.
    262         mStartState = STATE_DESTROY;
    263         getContext().stopService(service);
    264         waitForResultOrThrow(5 * 1000, "existing connection to lose service");
    265 
    266         getContext().unbindService(conn);
    267 
    268         conn = new TestConnection(true, true);
    269         success = false;
    270         try {
    271             // Expect to see the TestConnection connected.
    272             conn.setMonitor(true);
    273             mStartState = STATE_START_1;
    274             getContext().bindService(service, conn, 0);
    275             getContext().startService(service);
    276             waitForResultOrThrow(5 * 1000, "existing connection to receive service");
    277 
    278             success = true;
    279         } finally {
    280             if (!success) {
    281                 try {
    282                     getContext().stopService(service);
    283                     getContext().unbindService(conn);
    284                 } catch (Exception e) {
    285                     // eat
    286                 }
    287             }
    288         }
    289 
    290         // Expect to see the service unbind and then destroyed.
    291         conn.setMonitor(false);
    292         mStartState = STATE_UNBIND;
    293         getContext().stopService(service);
    294         waitForResultOrThrow(5 * 1000, "existing connection to lose service");
    295 
    296         getContext().unbindService(conn);
    297 
    298         conn = new TestConnection(true, true);
    299         success = false;
    300         try {
    301             // Expect to see the TestConnection connected.
    302             conn.setMonitor(true);
    303             mStartState = STATE_START_1;
    304             getContext().bindService(service, conn, 0);
    305             getContext().startService(service);
    306             waitForResultOrThrow(5 * 1000, "existing connection to receive service");
    307 
    308             success = true;
    309         } finally {
    310             if (!success) {
    311                 try {
    312                     getContext().stopService(service);
    313                     getContext().unbindService(conn);
    314                 } catch (Exception e) {
    315                     // eat
    316                 }
    317             }
    318         }
    319 
    320         // Expect to see the service unbind but not destroyed.
    321         conn.setMonitor(false);
    322         mStartState = STATE_UNBIND_ONLY;
    323         getContext().unbindService(conn);
    324         waitForResultOrThrow(5 * 1000, "existing connection to unbind service");
    325 
    326         // Expect to see the service rebound.
    327         mStartState = STATE_REBIND;
    328         getContext().bindService(service, conn, 0);
    329         waitForResultOrThrow(5 * 1000, "existing connection to rebind service");
    330 
    331         // Expect to see the service unbind and then destroyed.
    332         mStartState = STATE_UNBIND;
    333         getContext().stopService(service);
    334         waitForResultOrThrow(5 * 1000, "existing connection to lose service");
    335 
    336         getContext().unbindService(conn);
    337     }
    338 
    339     void bindAutoExpectResult(Intent service) {
    340         TestConnection conn = new TestConnection(false, true);
    341         boolean success = false;
    342         try {
    343             conn.setMonitor(true);
    344             mStartState = STATE_START_1;
    345             getContext().bindService(
    346                     service, conn, Context.BIND_AUTO_CREATE);
    347             waitForResultOrThrow(5 * 1000, "connection to start and receive service");
    348             success = true;
    349         } finally {
    350             if (!success) {
    351                 try {
    352                     getContext().unbindService(conn);
    353                 } catch (Exception e) {
    354                     // eat
    355                 }
    356             }
    357         }
    358         mStartState = STATE_UNBIND;
    359         getContext().unbindService(conn);
    360         waitForResultOrThrow(5 * 1000, "disconnecting from service");
    361     }
    362 
    363     void bindExpectNoPermission(Intent service) {
    364         TestConnection conn = new TestConnection(false, false);
    365         try {
    366             getContext().bindService(service, conn, Context.BIND_AUTO_CREATE);
    367             fail("Expected security exception when binding " + service);
    368         } catch (SecurityException e) {
    369             // expected
    370         } finally {
    371             getContext().unbindService(conn);
    372         }
    373     }
    374 
    375 
    376     @MediumTest
    377     public void testLocalStartClass() throws Exception {
    378         startExpectResult(new Intent(getContext(), LocalService.class));
    379     }
    380 
    381     @MediumTest
    382     public void testLocalStartAction() throws Exception {
    383         startExpectResult(new Intent(SERVICE_LOCAL));
    384     }
    385 
    386     @MediumTest
    387     public void testLocalBindClass() throws Exception {
    388         bindExpectResult(new Intent(getContext(), LocalService.class));
    389     }
    390 
    391     @MediumTest
    392     public void testLocalBindAction() throws Exception {
    393         bindExpectResult(new Intent(SERVICE_LOCAL));
    394     }
    395 
    396     @MediumTest
    397     public void testLocalBindAutoClass() throws Exception {
    398         bindAutoExpectResult(new Intent(getContext(), LocalService.class));
    399     }
    400 
    401     @MediumTest
    402     public void testLocalBindAutoAction() throws Exception {
    403         bindAutoExpectResult(new Intent(SERVICE_LOCAL));
    404     }
    405 
    406     @MediumTest
    407     public void testLocalStartClassPermissionGranted() throws Exception {
    408         startExpectResult(new Intent(getContext(), LocalGrantedService.class));
    409     }
    410 
    411     @MediumTest
    412     public void testLocalStartActionPermissionGranted() throws Exception {
    413         startExpectResult(new Intent(SERVICE_LOCAL_GRANTED));
    414     }
    415 
    416     @MediumTest
    417     public void testLocalBindClassPermissionGranted() throws Exception {
    418         bindExpectResult(new Intent(getContext(), LocalGrantedService.class));
    419     }
    420 
    421     @MediumTest
    422     public void testLocalBindActionPermissionGranted() throws Exception {
    423         bindExpectResult(new Intent(SERVICE_LOCAL_GRANTED));
    424     }
    425 
    426     @MediumTest
    427     public void testLocalBindAutoClassPermissionGranted() throws Exception {
    428         bindAutoExpectResult(new Intent(getContext(), LocalGrantedService.class));
    429     }
    430 
    431     @MediumTest
    432     public void testLocalBindAutoActionPermissionGranted() throws Exception {
    433         bindAutoExpectResult(new Intent(SERVICE_LOCAL_GRANTED));
    434     }
    435 
    436     @MediumTest
    437     public void testLocalStartClassPermissionDenied() throws Exception {
    438         startExpectNoPermission(new Intent(getContext(), LocalDeniedService.class));
    439     }
    440 
    441     @MediumTest
    442     public void testLocalStartActionPermissionDenied() throws Exception {
    443         startExpectNoPermission(new Intent(SERVICE_LOCAL_DENIED));
    444     }
    445 
    446     @MediumTest
    447     public void testLocalBindClassPermissionDenied() throws Exception {
    448         bindExpectNoPermission(new Intent(getContext(), LocalDeniedService.class));
    449     }
    450 
    451     @MediumTest
    452     public void testLocalBindActionPermissionDenied() throws Exception {
    453         bindExpectNoPermission(new Intent(SERVICE_LOCAL_DENIED));
    454     }
    455 
    456     @MediumTest
    457     public void testLocalUnbindTwice() throws Exception {
    458         EmptyConnection conn = new EmptyConnection();
    459         getContext().bindService(
    460                 new Intent(SERVICE_LOCAL_GRANTED), conn, 0);
    461         getContext().unbindService(conn);
    462         try {
    463             getContext().unbindService(conn);
    464             fail("No exception thrown on second unbind");
    465         } catch (IllegalArgumentException e) {
    466             //Log.i("foo", "Unbind exception", e);
    467         }
    468     }
    469 }
    470