| /* |
| * Copyright (C) 2006 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.content; |
| |
| import android.database.IContentObserver; |
| import android.net.Uri; |
| import android.os.Binder; |
| import android.os.RemoteException; |
| import android.os.IBinder; |
| import android.os.Parcel; |
| import android.os.ServiceManager; |
| import android.os.Bundle; |
| import android.util.Config; |
| import android.util.Log; |
| |
| /** |
| * {@hide} |
| */ |
| abstract class ContentServiceNative extends Binder implements IContentService |
| { |
| public ContentServiceNative() |
| { |
| attachInterface(this, descriptor); |
| } |
| |
| /** |
| * Cast a Binder object into a content resolver interface, generating |
| * a proxy if needed. |
| */ |
| static public IContentService asInterface(IBinder obj) |
| { |
| if (obj == null) { |
| return null; |
| } |
| IContentService in = |
| (IContentService)obj.queryLocalInterface(descriptor); |
| if (in != null) { |
| return in; |
| } |
| |
| return new ContentServiceProxy(obj); |
| } |
| |
| /** |
| * Retrieve the system's default/global content service. |
| */ |
| static public IContentService getDefault() |
| { |
| if (gDefault != null) { |
| return gDefault; |
| } |
| IBinder b = ServiceManager.getService("content"); |
| if (Config.LOGV) Log.v("ContentService", "default service binder = " + b); |
| gDefault = asInterface(b); |
| if (Config.LOGV) Log.v("ContentService", "default service = " + gDefault); |
| return gDefault; |
| } |
| |
| @Override |
| public boolean onTransact(int code, Parcel data, Parcel reply, int flags) |
| { |
| try { |
| switch (code) { |
| case 5038: { |
| data.readString(); // ignore the interface token that service generated |
| Uri uri = Uri.parse(data.readString()); |
| notifyChange(uri, null, false, false); |
| return true; |
| } |
| |
| case REGISTER_CONTENT_OBSERVER_TRANSACTION: { |
| Uri uri = Uri.CREATOR.createFromParcel(data); |
| boolean notifyForDescendents = data.readInt() != 0; |
| IContentObserver observer = IContentObserver.Stub.asInterface(data.readStrongBinder()); |
| registerContentObserver(uri, notifyForDescendents, observer); |
| return true; |
| } |
| |
| case UNREGISTER_CHANGE_OBSERVER_TRANSACTION: { |
| IContentObserver observer = IContentObserver.Stub.asInterface(data.readStrongBinder()); |
| unregisterContentObserver(observer); |
| return true; |
| } |
| |
| case NOTIFY_CHANGE_TRANSACTION: { |
| Uri uri = Uri.CREATOR.createFromParcel(data); |
| IContentObserver observer = IContentObserver.Stub.asInterface(data.readStrongBinder()); |
| boolean observerWantsSelfNotifications = data.readInt() != 0; |
| boolean syncToNetwork = data.readInt() != 0; |
| notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork); |
| return true; |
| } |
| |
| case START_SYNC_TRANSACTION: { |
| Uri url = null; |
| int hasUrl = data.readInt(); |
| if (hasUrl != 0) { |
| url = Uri.CREATOR.createFromParcel(data); |
| } |
| startSync(url, data.readBundle()); |
| return true; |
| } |
| |
| case CANCEL_SYNC_TRANSACTION: { |
| Uri url = null; |
| int hasUrl = data.readInt(); |
| if (hasUrl != 0) { |
| url = Uri.CREATOR.createFromParcel(data); |
| } |
| cancelSync(url); |
| return true; |
| } |
| |
| default: |
| return super.onTransact(code, data, reply, flags); |
| } |
| } catch (Exception e) { |
| Log.e("ContentServiceNative", "Caught exception in transact", e); |
| } |
| |
| return false; |
| } |
| |
| public IBinder asBinder() |
| { |
| return this; |
| } |
| |
| private static IContentService gDefault; |
| } |
| |
| |
| final class ContentServiceProxy implements IContentService |
| { |
| public ContentServiceProxy(IBinder remote) |
| { |
| mRemote = remote; |
| } |
| |
| public IBinder asBinder() |
| { |
| return mRemote; |
| } |
| |
| public void registerContentObserver(Uri uri, boolean notifyForDescendents, |
| IContentObserver observer) throws RemoteException |
| { |
| Parcel data = Parcel.obtain(); |
| uri.writeToParcel(data, 0); |
| data.writeInt(notifyForDescendents ? 1 : 0); |
| data.writeStrongInterface(observer); |
| mRemote.transact(REGISTER_CONTENT_OBSERVER_TRANSACTION, data, null, 0); |
| data.recycle(); |
| } |
| |
| public void unregisterContentObserver(IContentObserver observer) throws RemoteException { |
| Parcel data = Parcel.obtain(); |
| data.writeStrongInterface(observer); |
| mRemote.transact(UNREGISTER_CHANGE_OBSERVER_TRANSACTION, data, null, 0); |
| data.recycle(); |
| } |
| |
| public void notifyChange(Uri uri, IContentObserver observer, |
| boolean observerWantsSelfNotifications, boolean syncToNetwork) |
| throws RemoteException { |
| Parcel data = Parcel.obtain(); |
| uri.writeToParcel(data, 0); |
| data.writeStrongInterface(observer); |
| data.writeInt(observerWantsSelfNotifications ? 1 : 0); |
| data.writeInt(syncToNetwork ? 1 : 0); |
| mRemote.transact(NOTIFY_CHANGE_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); |
| data.recycle(); |
| } |
| |
| public void startSync(Uri url, Bundle extras) throws RemoteException { |
| Parcel data = Parcel.obtain(); |
| if (url == null) { |
| data.writeInt(0); |
| } else { |
| data.writeInt(1); |
| url.writeToParcel(data, 0); |
| } |
| extras.writeToParcel(data, 0); |
| mRemote.transact(START_SYNC_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); |
| data.recycle(); |
| } |
| |
| public void cancelSync(Uri url) throws RemoteException { |
| Parcel data = Parcel.obtain(); |
| if (url == null) { |
| data.writeInt(0); |
| } else { |
| data.writeInt(1); |
| url.writeToParcel(data, 0); |
| } |
| mRemote.transact(CANCEL_SYNC_TRANSACTION, data, null /* reply */, IBinder.FLAG_ONEWAY); |
| data.recycle(); |
| } |
| |
| private IBinder mRemote; |
| } |
| |