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