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 */ asInterface(IBinder obj)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 ServiceManagerNative()47 public ServiceManagerNative() 48 { 49 attachInterface(this, descriptor); 50 } 51 onTransact(int code, Parcel data, Parcel reply, int flags)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 int dumpPriority = data.readInt(); 78 addService(name, service, allowIsolated, dumpPriority); 79 return true; 80 } 81 82 case IServiceManager.LIST_SERVICES_TRANSACTION: { 83 data.enforceInterface(IServiceManager.descriptor); 84 int dumpPriority = data.readInt(); 85 String[] list = listServices(dumpPriority); 86 reply.writeStringArray(list); 87 return true; 88 } 89 90 case IServiceManager.SET_PERMISSION_CONTROLLER_TRANSACTION: { 91 data.enforceInterface(IServiceManager.descriptor); 92 IPermissionController controller = 93 IPermissionController.Stub.asInterface( 94 data.readStrongBinder()); 95 setPermissionController(controller); 96 return true; 97 } 98 } 99 } catch (RemoteException e) { 100 } 101 102 return false; 103 } 104 asBinder()105 public IBinder asBinder() 106 { 107 return this; 108 } 109 } 110 111 class ServiceManagerProxy implements IServiceManager { ServiceManagerProxy(IBinder remote)112 public ServiceManagerProxy(IBinder remote) { 113 mRemote = remote; 114 } 115 asBinder()116 public IBinder asBinder() { 117 return mRemote; 118 } 119 getService(String name)120 public IBinder getService(String name) throws RemoteException { 121 Parcel data = Parcel.obtain(); 122 Parcel reply = Parcel.obtain(); 123 data.writeInterfaceToken(IServiceManager.descriptor); 124 data.writeString(name); 125 mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0); 126 IBinder binder = reply.readStrongBinder(); 127 reply.recycle(); 128 data.recycle(); 129 return binder; 130 } 131 checkService(String name)132 public IBinder checkService(String name) throws RemoteException { 133 Parcel data = Parcel.obtain(); 134 Parcel reply = Parcel.obtain(); 135 data.writeInterfaceToken(IServiceManager.descriptor); 136 data.writeString(name); 137 mRemote.transact(CHECK_SERVICE_TRANSACTION, data, reply, 0); 138 IBinder binder = reply.readStrongBinder(); 139 reply.recycle(); 140 data.recycle(); 141 return binder; 142 } 143 addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)144 public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority) 145 throws RemoteException { 146 Parcel data = Parcel.obtain(); 147 Parcel reply = Parcel.obtain(); 148 data.writeInterfaceToken(IServiceManager.descriptor); 149 data.writeString(name); 150 data.writeStrongBinder(service); 151 data.writeInt(allowIsolated ? 1 : 0); 152 data.writeInt(dumpPriority); 153 mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0); 154 reply.recycle(); 155 data.recycle(); 156 } 157 listServices(int dumpPriority)158 public String[] listServices(int dumpPriority) throws RemoteException { 159 ArrayList<String> services = new ArrayList<String>(); 160 int n = 0; 161 while (true) { 162 Parcel data = Parcel.obtain(); 163 Parcel reply = Parcel.obtain(); 164 data.writeInterfaceToken(IServiceManager.descriptor); 165 data.writeInt(n); 166 data.writeInt(dumpPriority); 167 n++; 168 try { 169 boolean res = mRemote.transact(LIST_SERVICES_TRANSACTION, data, reply, 0); 170 if (!res) { 171 break; 172 } 173 } catch (RuntimeException e) { 174 // The result code that is returned by the C++ code can 175 // cause the call to throw an exception back instead of 176 // returning a nice result... so eat it here and go on. 177 break; 178 } 179 services.add(reply.readString()); 180 reply.recycle(); 181 data.recycle(); 182 } 183 String[] array = new String[services.size()]; 184 services.toArray(array); 185 return array; 186 } 187 setPermissionController(IPermissionController controller)188 public void setPermissionController(IPermissionController controller) 189 throws RemoteException { 190 Parcel data = Parcel.obtain(); 191 Parcel reply = Parcel.obtain(); 192 data.writeInterfaceToken(IServiceManager.descriptor); 193 data.writeStrongBinder(controller.asBinder()); 194 mRemote.transact(SET_PERMISSION_CONTROLLER_TRANSACTION, data, reply, 0); 195 reply.recycle(); 196 data.recycle(); 197 } 198 199 private IBinder mRemote; 200 } 201