1344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com/*
2344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * Copyright (C) 2012 Google Inc.
3344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com *
4344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * use this file except in compliance with the License. You may obtain a copy of
6344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * the License at
7344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com *
8344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * http://www.apache.org/licenses/LICENSE-2.0
9344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com *
10344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * Unless required by applicable law or agreed to in writing, software
11344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * License for the specific language governing permissions and limitations under
14344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * the License.
15344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com */
16344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
17344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.compackage com.googlecode.eyesfree.braille.translate;
18344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
19344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.comimport android.content.ComponentName;
20344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.comimport android.content.Context;
21344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.comimport android.content.Intent;
22344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.comimport android.content.ServiceConnection;
23344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.comimport android.os.Handler;
24344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.comimport android.os.IBinder;
25344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.comimport android.os.Message;
26344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.comimport android.os.RemoteException;
27344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.comimport android.util.Log;
28344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
29344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com/**
30344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * Client-side interface to the central braille translator service.
31344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com *
32344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * This class can be used to retrieve {@link BrailleTranslator} instances for
33344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * performing translation between text and braille cells.
34344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com *
35344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * Typically, an instance of this class is created at application
36344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * initialization time and destroyed using the {@link destroy()} method when
37344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * the application is about to be destroyed.  It is recommended that the
38344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * instance is destroyed and recreated if braille translation is not going to
39344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * be need for a long period of time.
40344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com *
41344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * Threading:<br>
42344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * The object must be destroyed on the same thread it was created.
43344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com * Other methods may be called from any thread.
44344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com */
45344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.compublic class TranslatorManager {
46344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private static final String LOG_TAG =
47344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            TranslatorManager.class.getSimpleName();
48344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private static final String ACTION_TRANSLATOR_SERVICE =
49344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            "com.googlecode.eyesfree.braille.service.ACTION_TRANSLATOR_SERVICE";
50344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private static final Intent mServiceIntent =
51344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            new Intent(ACTION_TRANSLATOR_SERVICE);
52344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    /**
53344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     * Delay before the first rebind attempt on bind error or service
54344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     * disconnect.
55344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     */
56344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private static final int REBIND_DELAY_MILLIS = 500;
57344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private static final int MAX_REBIND_ATTEMPTS = 5;
58344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    public static final int ERROR = -1;
59344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    public static final int SUCCESS = 0;
60344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
61344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    /**
62344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     * A callback interface to get notified when the translation
63344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     * manager is ready to be used, or an error occurred during
64344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     * initialization.
65344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     */
66344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    public interface OnInitListener {
67344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        /**
68344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com         * Called exactly once when it has been determined that the
69344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com         * translation service is either ready to be used ({@code SUCCESS})
70344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com         * or the service is not available {@code ERROR}.
71344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com         */
72344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        public void onInit(int status);
73344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    }
74344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
75344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private final Context mContext;
76344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private final TranslatorManagerHandler mHandler =
77344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            new TranslatorManagerHandler();
78344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private final ServiceCallback mServiceCallback = new ServiceCallback();
79344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
80344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private OnInitListener mOnInitListener;
81344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private Connection mConnection;
82344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private int mNumFailedBinds = 0;
83344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
84344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    /**
85344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     * Constructs an instance.  {@code context} is used to bind to the
86344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     * translator service.  The other methods of this class should not be
87344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     * called (they will fail) until {@code onInitListener.onInit()}
88344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     * is called.
89344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     */
90344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    public TranslatorManager(Context context, OnInitListener onInitListener) {
91344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        mContext = context;
92344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        mOnInitListener = onInitListener;
93344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        doBindService();
94344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    }
95344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
96344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    /**
97344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     * Destroys this instance, deallocating any global resources it is using.
98344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     * Any {@link BrailleTranslator} objects that were created using this
99344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     * object are invalid after this call.
100344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     */
101344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    public void destroy() {
102344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        doUnbindService();
103344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        mHandler.destroy();
104344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    }
105344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
106344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    /**
107344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     * Returns a new {@link BrailleTranslator} for the translation
108344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     * table specified by {@code tableName}.
109344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com     */
110344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    // TODO: Document how to discover valid table names.
111344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    public BrailleTranslator getTranslator(String tableName) {
112344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        ITranslatorService localService = getTranslatorService();
113344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        if (localService != null) {
114344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            try {
115344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                if (localService.checkTable(tableName)) {
116344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                    return new BrailleTranslatorImpl(tableName);
117344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                }
118344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            } catch (RemoteException ex) {
119344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                Log.e(LOG_TAG, "Error in getTranslator", ex);
120344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            }
121344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        }
122344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        return null;
123344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    }
124344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
125344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private void doBindService() {
126344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        Connection localConnection = new Connection();
127344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        if (!mContext.bindService(mServiceIntent, localConnection,
128344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                Context.BIND_AUTO_CREATE)) {
129344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            Log.e(LOG_TAG, "Failed to bind to service");
130344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            mHandler.scheduleRebind();
131344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            return;
132344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        }
133344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        mConnection = localConnection;
134344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        Log.i(LOG_TAG, "Bound to translator service");
135344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    }
136344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
137344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private void doUnbindService() {
138344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        if (mConnection != null) {
139344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            mContext.unbindService(mConnection);
140344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            mConnection = null;
141344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        }
142344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    }
143344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
144344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private ITranslatorService getTranslatorService() {
145344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        Connection localConnection = mConnection;
146344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        if (localConnection != null) {
147344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            return localConnection.mService;
148344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        }
149344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        return null;
150344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    }
151344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
152344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private class Connection implements ServiceConnection {
153344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        // Read in application threads, written in main thread.
154344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        private volatile ITranslatorService mService;
155344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
156344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        @Override
157344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        public void onServiceConnected(ComponentName className,
158344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                IBinder binder) {
159344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            Log.i(LOG_TAG, "Connected to translation service");
160344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            ITranslatorService localService =
161344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                    ITranslatorService.Stub.asInterface(binder);
162344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            try {
163344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                localService.setCallback(mServiceCallback);
164344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                mService = localService;
165344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                synchronized (mHandler) {
166344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                    mNumFailedBinds = 0;
167344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                }
168344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            } catch (RemoteException ex) {
169344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                // Service went away, rely on disconnect handler to
170344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                // schedule a rebind.
171344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                Log.e(LOG_TAG, "Error when setting callback", ex);
172344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            }
173344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        }
174344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
175344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        @Override
176344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        public void onServiceDisconnected(ComponentName className) {
177344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            Log.e(LOG_TAG, "Disconnected from translator service");
178344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            mService = null;
179344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            // Retry by rebinding, and finally call the onInit if aplicable.
180344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            mHandler.scheduleRebind();
181344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        }
182344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    }
183344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
184344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private class BrailleTranslatorImpl implements BrailleTranslator {
185344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        private final String mTable;
186344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
187344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        public BrailleTranslatorImpl(String table) {
188344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            mTable = table;
189344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        }
190344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
191344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        @Override
192344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        public byte[] translate(String text) {
193344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            ITranslatorService localService = getTranslatorService();
194344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            if (localService != null) {
195344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                try {
196344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                    return localService.translate(text, mTable);
197344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                } catch (RemoteException ex) {
198344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                    Log.e(LOG_TAG, "Error in translate", ex);
199344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                }
200344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            }
201344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            return null;
202344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        }
203344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
204344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        @Override
205344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        public String backTranslate(byte[] cells) {
206344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            ITranslatorService localService = getTranslatorService();
207344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            if (localService != null) {
208344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                try {
209344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                    return localService.backTranslate(cells, mTable);
210344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                } catch (RemoteException ex) {
211344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                    Log.e(LOG_TAG, "Error in backTranslate", ex);
212344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                }
213344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            }
214344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            return null;
215344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        }
216344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    }
217344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
218344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private class ServiceCallback extends ITranslatorServiceCallback.Stub {
219344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        @Override
220344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        public void onInit(int status) {
221344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            mHandler.onInit(status);
222344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        }
223344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    }
224344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
225344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    private class TranslatorManagerHandler extends Handler {
226344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        private static final int MSG_ON_INIT = 1;
227344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        private static final int MSG_REBIND_SERVICE = 2;
228344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
229344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        public void onInit(int status) {
230344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            obtainMessage(MSG_ON_INIT, status, 0).sendToTarget();
231344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        }
232344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
233344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        public void destroy() {
234344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            mOnInitListener = null;
235344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            // Cacnel outstanding messages, most importantly
236344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            // scheduled rebinds.
237344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            removeCallbacksAndMessages(null);
238344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        }
239344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
240344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        public void scheduleRebind() {
241344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            synchronized (this) {
242344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                if (mNumFailedBinds < MAX_REBIND_ATTEMPTS) {
243344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                    int delay = REBIND_DELAY_MILLIS << mNumFailedBinds;
244344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                    sendEmptyMessageDelayed(MSG_REBIND_SERVICE, delay);
245344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                    ++mNumFailedBinds;
246344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                } else {
247344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                    onInit(ERROR);
248344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                }
249344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            }
250344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        }
251344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
252344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        @Override
253344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        public void handleMessage(Message msg) {
254344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            switch (msg.what) {
255344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                case MSG_ON_INIT:
256344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                    handleOnInit(msg.arg1);
257344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                    break;
258344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                case MSG_REBIND_SERVICE:
259344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                    handleRebindService();
260344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                    break;
261344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            }
262344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        }
263344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
264344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        private void handleOnInit(int status) {
265344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            if (mOnInitListener != null) {
266344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                mOnInitListener.onInit(status);
267344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                mOnInitListener = null;
268344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            }
269344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        }
270344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com
271344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        private void handleRebindService() {
272344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            if (mConnection != null) {
273344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com                doUnbindService();
274344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            }
275344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com            doBindService();
276344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com        }
277344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com    }
278344caf0bfb20161349dbf2f658a7f096a08ea76plundblad@google.com}
279