Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2008 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.os.cts;
     18 
     19 
     20 import android.content.ComponentName;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.ServiceConnection;
     24 import android.os.IBinder;
     25 import android.os.IInterface;
     26 import android.os.RemoteCallbackList;
     27 import android.os.RemoteException;
     28 import android.test.AndroidTestCase;
     29 
     30 public class RemoteCallbackListTest extends AndroidTestCase {
     31     private static final String SERVICE_ACTION = "android.app.REMOTESERVICE";
     32 
     33     private ISecondary mSecondaryService = null;
     34     // Lock object
     35     private Sync mSync = new Sync();
     36     private Intent mIntent;
     37     private Context mContext;
     38     private ServiceConnection mSecondaryConnection;
     39 
     40     @Override
     41     protected void setUp() throws Exception {
     42         super.setUp();
     43         mContext = getContext();
     44         mSecondaryConnection = new ServiceConnection() {
     45             public void onServiceConnected(ComponentName className, IBinder service) {
     46                 mSecondaryService = ISecondary.Stub.asInterface(service);
     47                 synchronized (mSync) {
     48                     mSync.mIsConnected = true;
     49                     mSync.notify();
     50                 }
     51             }
     52 
     53             public void onServiceDisconnected(ComponentName className) {
     54                 mSecondaryService = null;
     55                 synchronized (mSync) {
     56                     mSync.mIsDisConnected = true;
     57                     mSync.notify();
     58                 }
     59             }
     60         };
     61         mIntent = new Intent(SERVICE_ACTION);
     62         mIntent.setPackage(mContext.getPackageName());
     63 
     64         Intent secondaryIntent = new Intent(ISecondary.class.getName());
     65         secondaryIntent.setPackage(mContext.getPackageName());
     66         assertTrue(mContext.bindService(secondaryIntent, mSecondaryConnection,
     67                 Context.BIND_AUTO_CREATE));
     68 
     69     }
     70 
     71     private static class Sync {
     72         public boolean mIsConnected;
     73         public boolean mIsDisConnected;
     74     }
     75 
     76     @Override
     77     public void tearDown() throws Exception {
     78         super.tearDown();
     79         if (mSecondaryConnection != null) {
     80             mContext.unbindService(mSecondaryConnection);
     81         }
     82         if (mIntent != null) {
     83             mContext.stopService(mIntent);
     84         }
     85     }
     86 
     87     public void testRemoteCallbackList() throws Exception {
     88         // Test constructor(default one).
     89         MockRemoteCallbackList<IInterface> rc = new MockRemoteCallbackList<IInterface>();
     90         synchronized (mSync) {
     91             if (!mSync.mIsConnected) {
     92                 mSync.wait();
     93             }
     94         }
     95 
     96         try {
     97             rc.register(null);
     98             fail("Should throw NullPointerException");
     99         } catch (NullPointerException e) {
    100             // excepted
    101         }
    102 
    103         try {
    104             rc.unregister(null);
    105             fail("Should throw NullPointerException");
    106         } catch (NullPointerException e) {
    107             // expected
    108         }
    109 
    110         int servicePid = mSecondaryService.getPid();
    111         // Test beginBroadcast, register, unregister. There is only one service binded.
    112         assertTrue(rc.register(mSecondaryService));
    113         int index = rc.beginBroadcast();
    114         assertEquals(1, index);
    115         IInterface actual = rc.getBroadcastItem(index - 1);
    116         assertNotNull(actual);
    117         assertSame(mSecondaryService, actual);
    118         // Test finishBroadcast(Is it valid to use rc.getBroadcastItem after finishBroadcast)
    119         rc.finishBroadcast();
    120         assertTrue(rc.unregister(mSecondaryService));
    121 
    122         rc.register(mSecondaryService);
    123         rc.beginBroadcast();
    124         // Process killed. No need to call finishBroadcast, unregister
    125         android.os.Process.killProcess(servicePid);
    126 
    127         synchronized (mSync) {
    128             if (!mSync.mIsDisConnected) {
    129                 mSync.wait();
    130             }
    131         }
    132         // sleep some time to wait for onCallbackDied called.
    133         Thread.sleep(1000);
    134         // Test onCallbackDied
    135         assertTrue(rc.isOnCallbackDiedCalled);
    136     }
    137 
    138     public void testKill() {
    139         MockRemoteCallbackList<IInterface> rc = new MockRemoteCallbackList<IInterface>();
    140         synchronized (mSync) {
    141             if (!mSync.mIsConnected) {
    142                 try {
    143                     mSync.wait();
    144                 } catch (InterruptedException e) {
    145                     fail("Throw InterruptedException: " + e.getMessage());
    146                 }
    147             }
    148         }
    149 
    150         rc.register(mSecondaryService);
    151         rc.beginBroadcast();
    152         rc.finishBroadcast();
    153         rc.kill();
    154         // kill() should unregister the callback (beginBroadcast()
    155         // should return 0) and not allow registering the service again.
    156         assertEquals(0, rc.beginBroadcast());
    157         assertFalse(rc.register(mSecondaryService));
    158     }
    159 
    160     private class MockRemoteCallbackList<E extends IInterface> extends RemoteCallbackList<E> {
    161         public boolean isOnCallbackDiedCalled;
    162 
    163         @Override
    164         public void onCallbackDied(E callback) {
    165             isOnCallbackDiedCalled = true;
    166             super.onCallbackDied(callback);
    167         }
    168     }
    169 }
    170