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.os; 18 19 import java.util.ArrayList; 20 21 22 /** 23 * Native implementation of the service manager. Most clients will only 24 * care about getDefault() and possibly asInterface(). 25 * @hide 26 */ 27 public abstract class ServiceManagerNative extends Binder implements IServiceManager 28 { 29 /** 30 * Cast a Binder object into a service manager interface, generating 31 * a proxy if needed. 32 */ 33 static public IServiceManager asInterface(IBinder obj) 34 { 35 if (obj == null) { 36 return null; 37 } 38 IServiceManager in = 39 (IServiceManager)obj.queryLocalInterface(descriptor); 40 if (in != null) { 41 return in; 42 } 43 44 return new ServiceManagerProxy(obj); 45 } 46 47 public ServiceManagerNative() 48 { 49 attachInterface(this, descriptor); 50 } 51 52 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 53 { 54 try { 55 switch (code) { 56 case IServiceManager.GET_SERVICE_TRANSACTION: { 57 data.enforceInterface(IServiceManager.descriptor); 58 String name = data.readString(); 59 IBinder service = getService(name); 60 reply.writeStrongBinder(service); 61 return true; 62 } 63 64 case IServiceManager.CHECK_SERVICE_TRANSACTION: { 65 data.enforceInterface(IServiceManager.descriptor); 66 String name = data.readString(); 67 IBinder service = checkService(name); 68 reply.writeStrongBinder(service); 69 return true; 70 } 71 72 case IServiceManager.ADD_SERVICE_TRANSACTION: { 73 data.enforceInterface(IServiceManager.descriptor); 74 String name = data.readString(); 75 IBinder service = data.readStrongBinder(); 76 boolean allowIsolated = data.readInt() != 0; 77 addService(name, service, allowIsolated); 78 return true; 79 } 80 81 case IServiceManager.LIST_SERVICES_TRANSACTION: { 82 data.enforceInterface(IServiceManager.descriptor); 83 String[] list = listServices(); 84 reply.writeStringArray(list); 85 return true; 86 } 87 88 case IServiceManager.SET_PERMISSION_CONTROLLER_TRANSACTION: { 89 data.enforceInterface(IServiceManager.descriptor); 90 IPermissionController controller 91 = IPermissionController.Stub.asInterface( 92 data.readStrongBinder()); 93 setPermissionController(controller); 94 return true; 95 } 96 } 97 } catch (RemoteException e) { 98 } 99 100 return false; 101 } 102 103 public IBinder asBinder() 104 { 105 return this; 106 } 107 } 108 109 class ServiceManagerProxy implements IServiceManager { 110 public ServiceManagerProxy(IBinder remote) { 111 mRemote = remote; 112 } 113 114 public IBinder asBinder() { 115 return mRemote; 116 } 117 118 public IBinder getService(String name) throws RemoteException { 119 Parcel data = Parcel.obtain(); 120 Parcel reply = Parcel.obtain(); 121 data.writeInterfaceToken(IServiceManager.descriptor); 122 data.writeString(name); 123 mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0); 124 IBinder binder = reply.readStrongBinder(); 125 reply.recycle(); 126 data.recycle(); 127 return binder; 128 } 129 130 public IBinder checkService(String name) throws RemoteException { 131 Parcel data = Parcel.obtain(); 132 Parcel reply = Parcel.obtain(); 133 data.writeInterfaceToken(IServiceManager.descriptor); 134 data.writeString(name); 135 mRemote.transact(CHECK_SERVICE_TRANSACTION, data, reply, 0); 136 IBinder binder = reply.readStrongBinder(); 137 reply.recycle(); 138 data.recycle(); 139 return binder; 140 } 141 142 public void addService(String name, IBinder service, boolean allowIsolated) 143 throws RemoteException { 144 Parcel data = Parcel.obtain(); 145 Parcel reply = Parcel.obtain(); 146 data.writeInterfaceToken(IServiceManager.descriptor); 147 data.writeString(name); 148 data.writeStrongBinder(service); 149 data.writeInt(allowIsolated ? 1 : 0); 150 mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0); 151 reply.recycle(); 152 data.recycle(); 153 } 154 155 public String[] listServices() throws RemoteException { 156 ArrayList<String> services = new ArrayList<String>(); 157 int n = 0; 158 while (true) { 159 Parcel data = Parcel.obtain(); 160 Parcel reply = Parcel.obtain(); 161 data.writeInterfaceToken(IServiceManager.descriptor); 162 data.writeInt(n); 163 n++; 164 try { 165 boolean res = mRemote.transact(LIST_SERVICES_TRANSACTION, data, reply, 0); 166 if (!res) { 167 break; 168 } 169 } catch (RuntimeException e) { 170 // The result code that is returned by the C++ code can 171 // cause the call to throw an exception back instead of 172 // returning a nice result... so eat it here and go on. 173 break; 174 } 175 services.add(reply.readString()); 176 reply.recycle(); 177 data.recycle(); 178 } 179 String[] array = new String[services.size()]; 180 services.toArray(array); 181 return array; 182 } 183 184 public void setPermissionController(IPermissionController controller) 185 throws RemoteException { 186 Parcel data = Parcel.obtain(); 187 Parcel reply = Parcel.obtain(); 188 data.writeInterfaceToken(IServiceManager.descriptor); 189 data.writeStrongBinder(controller.asBinder()); 190 mRemote.transact(SET_PERMISSION_CONTROLLER_TRANSACTION, data, reply, 0); 191 reply.recycle(); 192 data.recycle(); 193 } 194 195 private IBinder mRemote; 196 } 197