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 
17 package com.android.internal.util;
18 
19 import android.app.Service;
20 import android.content.Intent;
21 import android.os.Handler;
22 import android.os.IBinder;
23 import android.os.Message;
24 import android.os.Messenger;
25 import 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  */
35 abstract 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      */
createHandler()70     abstract public AsyncServiceInfo createHandler();
71 
72     /**
73      * Get the handler
74      */
getHandler()75     public Handler getHandler() {
76         return mHandler;
77     }
78 
79     /**
80      * onCreate
81      */
82     @Override
onCreate()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
onStartCommand(Intent intent, int flags, int startId)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
onDestroy()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
onBind(Intent intent)125     public IBinder onBind(Intent intent) {
126         return mMessenger.getBinder();
127     }
128 }
129