1/**
2 * Copyright (C) 2010 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
17package com.android.internal.util;
18
19import android.app.Service;
20import android.content.Intent;
21import android.os.Handler;
22import android.os.IBinder;
23import android.os.Message;
24import android.os.Messenger;
25import android.util.Slog;
26
27/**
28 * A service that receives Intents and IBinder transactions
29 * as messages via an AsyncChannel.
30 * <p>
31 * The Start Intent arrives as CMD_ASYNC_SERVICE_ON_START_INTENT with msg.arg1 = flags,
32 * msg.arg2 = startId, and msg.obj = intent.
33 * <p>
34 */
35abstract public class AsyncService extends Service {
36    private static final String TAG = "AsyncService";
37
38    protected static final boolean DBG = true;
39
40    /** The command sent when a onStartCommand is invoked */
41    public static final int CMD_ASYNC_SERVICE_ON_START_INTENT = IBinder.LAST_CALL_TRANSACTION;
42
43    /** The command sent when a onDestroy is invoked */
44    public static final int CMD_ASYNC_SERVICE_DESTROY = IBinder.LAST_CALL_TRANSACTION + 1;
45
46    /** Messenger transport */
47    protected Messenger mMessenger;
48
49    /** Message Handler that will receive messages */
50    Handler mHandler;
51
52    public static final class AsyncServiceInfo {
53        /** Message Handler that will receive messages */
54        public Handler mHandler;
55
56        /**
57         * The flags returned by onStartCommand on how to restart.
58         * For instance @see android.app.Service#START_STICKY
59         */
60        public int mRestartFlags;
61    }
62
63    AsyncServiceInfo mAsyncServiceInfo;
64
65    /**
66     * Create the service's handler returning AsyncServiceInfo.
67     *
68     * @return AsyncServiceInfo
69     */
70    abstract public AsyncServiceInfo createHandler();
71
72    /**
73     * Get the handler
74     */
75    public Handler getHandler() {
76        return mHandler;
77    }
78
79    /**
80     * onCreate
81     */
82    @Override
83    public void onCreate() {
84        super.onCreate();
85        mAsyncServiceInfo = createHandler();
86        mHandler = mAsyncServiceInfo.mHandler;
87        mMessenger = new Messenger(mHandler);
88    }
89
90    /**
91     * Sends the CMD_ASYNC_SERVICE_ON_START_INTENT message.
92     */
93    @Override
94    public int onStartCommand(Intent intent, int flags, int startId) {
95        if (DBG) Slog.d(TAG, "onStartCommand");
96
97        Message msg = mHandler.obtainMessage();
98        msg.what = CMD_ASYNC_SERVICE_ON_START_INTENT;
99        msg.arg1 = flags;
100        msg.arg2 = startId;
101        msg.obj = intent;
102        mHandler.sendMessage(msg);
103
104        return mAsyncServiceInfo.mRestartFlags;
105    }
106
107    /**
108     * Called when service is destroyed. After returning the
109     * service is dead and no more processing should be expected
110     * to occur.
111     */
112    @Override
113    public void onDestroy() {
114        if (DBG) Slog.d(TAG, "onDestroy");
115
116        Message msg = mHandler.obtainMessage();
117        msg.what = CMD_ASYNC_SERVICE_DESTROY;
118        mHandler.sendMessage(msg);
119    }
120
121    /**
122     * Returns the Messenger's binder.
123     */
124    @Override
125    public IBinder onBind(Intent intent) {
126        return mMessenger.getBinder();
127    }
128}
129