OSDN Git Service

Clear the Parcel before writing an exception during a transaction
[android-x86/frameworks-base.git] / core / java / android / os / ServiceManagerNative.java
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 }