CarDrawerActivity.java revision 13df550560fd8e7e6287603a112659cca244eeee
1da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen/*
2da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen * Copyright (C) 2015 The Android Open Source Project
3da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen *
4da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen * Licensed under the Apache License, Version 2.0 (the "License");
5da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen * you may not use this file except in compliance with the License.
6da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen * You may obtain a copy of the License at
7da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen *
8da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen *      http://www.apache.org/licenses/LICENSE-2.0
9da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen *
10da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen * Unless required by applicable law or agreed to in writing, software
11da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen * distributed under the License is distributed on an "AS IS" BASIS,
12da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen * See the License for the specific language governing permissions and
14da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen * limitations under the License.
15da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen */
16da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
17da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenpackage android.support.car.app.menu;
18da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
19da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport android.content.Context;
20da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport android.graphics.Bitmap;
21da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport android.graphics.drawable.Drawable;
2270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chenimport android.hardware.input.InputManager;
23da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport android.os.Bundle;
24da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport android.os.Handler;
25da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport android.os.IBinder;
26da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport android.os.RemoteException;
27da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport android.support.annotation.LayoutRes;
2813df550560fd8e7e6287603a112659cca244eeeeYao Chenimport android.support.car.Car;
29868f9e6e890eeaf3281e55475f102cb677d6032aYao Chenimport android.support.car.app.CarFragmentActivity;
3070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chenimport android.support.car.input.CarEditable;
3170f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chenimport android.support.car.input.CarEditableListener;
3270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chenimport android.support.car.input.CarInputManager;
3370f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chenimport android.support.car.input.CarRestrictedEditText;
3403100f7264789a3f36713b0dd69363ce4785435aYao Chenimport android.support.v4.app.Fragment;
35da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport android.util.DisplayMetrics;
36da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport android.util.Log;
37da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport android.view.LayoutInflater;
38da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport android.view.View;
39da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport android.view.ViewGroup;
4070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chenimport android.view.WindowManager;
4170f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chenimport android.view.inputmethod.EditorInfo;
4270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chenimport android.view.inputmethod.InputConnection;
4370f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chenimport android.view.inputmethod.InputConnectionWrapper;
4470f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chenimport android.view.inputmethod.InputMethodManager;
4570f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chenimport android.widget.EditText;
46da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
47da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
48da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport java.lang.ref.WeakReference;
49da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport java.util.ArrayList;
50da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport java.util.HashMap;
51da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport java.util.List;
52da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chenimport java.util.Map;
53da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
54da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen/**
55da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen * Base class for a car app which wants to use a drawer.
56da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen */
57868f9e6e890eeaf3281e55475f102cb677d6032aYao Chenpublic abstract class CarDrawerActivity extends CarFragmentActivity {
58da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    private static final String TAG = "CarDrawerActivity";
59da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    private static final String KEY_DRAWERSHOWING =
60da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            "android.support.car.app.CarDrawerActivity.DRAWER_SHOWING";
6170f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    private static final String KEY_INPUTSHOWING =
6270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            "android.support.car.app.CarDrawerActivity.INPUT_SHOWING";
6370f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    private static final String KEY_SEARCHBOXENABLED =
6470f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            "android.support.car.app.CarDrawerActivity.SEARCH_BOX_ENABLED";
65da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
66da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    private final Handler mHandler = new Handler();
6770f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    private final CarUiController mUiController;
68da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
69da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    private CarMenuCallbacks mMenuCallbacks;
70da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    private CarMenuCallbacksBinder mBinder;
71da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    private boolean mDrawerShowing;
7270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    private boolean mShowingSearchBox;
7370f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    private boolean mSearchBoxEnabled;
74da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    private boolean mOnCreateCalled = false;
7570f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    private View.OnClickListener mSearchBoxOnClickListener;
7670f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
7770f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    private CarInputManager mInputManager;
7870f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    private EditText mSearchBoxView;
7970f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
8070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    /**
8170f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     * Simple interface to listen for keyboard events.
8270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     */
8370f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    public interface SearchBoxEditListener {
8470f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        /**
8570f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen         * The user hit enter on the keyboard.
8670f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen         */
8770f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        void onSearch(String text);
8870f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
8970f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        /**
9070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen         * The user changed the text in the search box with the keyboard.
9170f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen         */
9270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        void onEdit(String text);
9370f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    }
94da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
9513df550560fd8e7e6287603a112659cca244eeeeYao Chen    public CarDrawerActivity(Proxy proxy, Context context, Car car) {
9613df550560fd8e7e6287603a112659cca244eeeeYao Chen        super(proxy, context, car);
97da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mUiController = new CarUiController(this);
98da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
99da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
100da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    @Override
101da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    public void setContentView(View view) {
102da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        ViewGroup parent = (ViewGroup) findViewById(mUiController.getFragmentContainerId());
103da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        parent.addView(view);
104da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
105da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
106da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    @Override
107da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    public void setContentView(@LayoutRes int resourceId) {
108da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        ViewGroup parent = (ViewGroup) findViewById(mUiController.getFragmentContainerId());
109da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        LayoutInflater inflater = getLayoutInflater();
110da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        inflater.inflate(resourceId, parent, true);
111da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
112da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
113da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    public void setContentFragment(Fragment fragment) {
114da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        super.setContentFragment(fragment, mUiController.getFragmentContainerId());
115da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
116da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
11703100f7264789a3f36713b0dd69363ce4785435aYao Chen    @Override
11803100f7264789a3f36713b0dd69363ce4785435aYao Chen    public View findViewById(@LayoutRes int id) {
11903100f7264789a3f36713b0dd69363ce4785435aYao Chen        return super.findViewById(mUiController.getFragmentContainerId()).findViewById(id);
12003100f7264789a3f36713b0dd69363ce4785435aYao Chen    }
12103100f7264789a3f36713b0dd69363ce4785435aYao Chen
122d33cc25ece71923740ebc87be2048475b452cf0bYao Chen    @Override
123d33cc25ece71923740ebc87be2048475b452cf0bYao Chen    protected void onStart() {
124d33cc25ece71923740ebc87be2048475b452cf0bYao Chen        super.onStart();
12570f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
126d33cc25ece71923740ebc87be2048475b452cf0bYao Chen        mUiController.onStart();
127d33cc25ece71923740ebc87be2048475b452cf0bYao Chen    }
128d33cc25ece71923740ebc87be2048475b452cf0bYao Chen
129d33cc25ece71923740ebc87be2048475b452cf0bYao Chen    @Override
130d33cc25ece71923740ebc87be2048475b452cf0bYao Chen    protected void onResume() {
131d33cc25ece71923740ebc87be2048475b452cf0bYao Chen        super.onResume();
132d33cc25ece71923740ebc87be2048475b452cf0bYao Chen        mUiController.onResume();
133d33cc25ece71923740ebc87be2048475b452cf0bYao Chen    }
134d33cc25ece71923740ebc87be2048475b452cf0bYao Chen
135d33cc25ece71923740ebc87be2048475b452cf0bYao Chen    @Override
136d33cc25ece71923740ebc87be2048475b452cf0bYao Chen    protected void onPause() {
137d33cc25ece71923740ebc87be2048475b452cf0bYao Chen        super.onPause();
138d33cc25ece71923740ebc87be2048475b452cf0bYao Chen        mUiController.onPause();
139d33cc25ece71923740ebc87be2048475b452cf0bYao Chen    }
140d33cc25ece71923740ebc87be2048475b452cf0bYao Chen
141d33cc25ece71923740ebc87be2048475b452cf0bYao Chen    @Override
142d33cc25ece71923740ebc87be2048475b452cf0bYao Chen    protected void onStop() {
143d33cc25ece71923740ebc87be2048475b452cf0bYao Chen        super.onStop();
144d33cc25ece71923740ebc87be2048475b452cf0bYao Chen        mUiController.onStop();
145d33cc25ece71923740ebc87be2048475b452cf0bYao Chen    }
146d33cc25ece71923740ebc87be2048475b452cf0bYao Chen
1479d3fdf2eed6187804c78df5952e7290f5ed15fc3Yao Chen    public int getFragmentContainerId() {
1489d3fdf2eed6187804c78df5952e7290f5ed15fc3Yao Chen        return mUiController.getFragmentContainerId();
1499d3fdf2eed6187804c78df5952e7290f5ed15fc3Yao Chen    }
1509d3fdf2eed6187804c78df5952e7290f5ed15fc3Yao Chen
151da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    public interface OnMenuClickListener {
152da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        /**
153da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen         * Called when the menu button is clicked.
154da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen         *
155da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen         * @return True if event was handled. This will prevent the drawer from executing its
156da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen         *         default action (opening/closing/going back). False if the event was not handled
157da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen         *         so the drawer will execute the default action.
158da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen         */
159da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        boolean onClicked();
160da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
161da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
162da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    public void setCarMenuCallbacks(final CarMenuCallbacks callbacks) {
163da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        if (mOnCreateCalled) {
164da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            throw new IllegalStateException(
165da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    "Cannot call setCarMenuCallbacks after onCreate has been called.");
166da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
167da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mMenuCallbacks = callbacks;
168da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
169da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
170da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    /**
171da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     * Listener that listens for when the menu button is pressed.
172da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     *
173da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     * @param listener {@link OnMenuClickListener} that will listen for menu button clicks.
174da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     */
175da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    public void setOnMenuClickedListener(OnMenuClickListener listener) {
176da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mBinder.setOnMenuClickedListener(listener);
177da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
178da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
179f4a72c4f1aa2394c6c289ed89dcb95cde548f236Aidan Snoswell    /**
180f4a72c4f1aa2394c6c289ed89dcb95cde548f236Aidan Snoswell     * Restore the menu button drawable
181f4a72c4f1aa2394c6c289ed89dcb95cde548f236Aidan Snoswell     */
182f4a72c4f1aa2394c6c289ed89dcb95cde548f236Aidan Snoswell    public void restoreMenuButtonDrawable() {
183f4a72c4f1aa2394c6c289ed89dcb95cde548f236Aidan Snoswell        mUiController.restoreMenuButtonDrawable();
184f4a72c4f1aa2394c6c289ed89dcb95cde548f236Aidan Snoswell    }
185f4a72c4f1aa2394c6c289ed89dcb95cde548f236Aidan Snoswell
186f4a72c4f1aa2394c6c289ed89dcb95cde548f236Aidan Snoswell    /**
187f4a72c4f1aa2394c6c289ed89dcb95cde548f236Aidan Snoswell     * Sets the menu button bitmap
188f4a72c4f1aa2394c6c289ed89dcb95cde548f236Aidan Snoswell     *
189f4a72c4f1aa2394c6c289ed89dcb95cde548f236Aidan Snoswell     * @param bitmap Bitmap to the menu button to.
190f4a72c4f1aa2394c6c289ed89dcb95cde548f236Aidan Snoswell     */
191f4a72c4f1aa2394c6c289ed89dcb95cde548f236Aidan Snoswell    public void setMenuButtonBitmap(Bitmap bitmap) {
192f4a72c4f1aa2394c6c289ed89dcb95cde548f236Aidan Snoswell        mUiController.setMenuButtonBitmap(bitmap);
193f4a72c4f1aa2394c6c289ed89dcb95cde548f236Aidan Snoswell    }
194da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
195da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    /**
196da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     * Set the title of the menu.
197da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     */
198da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    public void setTitle(CharSequence title) {
199da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mUiController.setTitle(title);
200da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
201da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
202da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    /**
203da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     * Set the System UI to be light.
204da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     */
205da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    public void setLightMode() {
206da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mUiController.setLightMode();
207da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
208da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
209da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    /**
210da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     * Set the System UI to be dark.
211da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     */
212da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    public void setDarkMode() {
213da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mUiController.setDarkMode();
214da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
215da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
216da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    /**
217da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     * Set the System UI to be dark during day mode and light during night mode.
218da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     */
219da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    public void setAutoLightDarkMode() {
220da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mUiController.setAutoLightDarkMode();
221da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
222da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
223da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    /**
224da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     * Sets the application background to the given {@link android.graphics.Bitmap}.
225da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     *
226da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     * @param bitmap to use as background.
227da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     */
228da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    public void setBackground(Bitmap bitmap) {
229da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mUiController.setBackground(bitmap);
230da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
231da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
232da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    /**
233da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     * Sets the background to a given resource.
234da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     * The resource should refer to a Drawable object or 0 to remove the background.
235da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     *
236da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     * @param resId The identifier of the resource.
237da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     */
238da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    public void setBackgroundResource(int resId) {
239da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mUiController.setBackgroundResource(resId);
240da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
241da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
242da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    public void setScrimColor(int color) {
243da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mUiController.setScrimColor(color);
244da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
245da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
246da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    /**
247da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     * Show the menu associated with the given id in the drawer.
248da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     *
249da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     * @param id Id of the menu to link to.
250da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     * @param title Title that should be displayed.
251da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen     */
252da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    public void showMenu(String id, String title) {
253da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mUiController.showMenu(id, title);
254da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
255da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
256da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    private void registerCarMenuCallbacks(IBinder callbacks) {
257da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mUiController.registerCarMenuCallbacks(callbacks);
258da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
259da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
260da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    private final CarMenuCallbacks.OnChildrenChangedListener mMenuListener =
261da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            new CarMenuCallbacks.OnChildrenChangedListener() {
262da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                @Override
263da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                public void onChildrenChanged(String parentId) {
264da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    if (mOnCreateCalled) {
265da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                        mBinder.onChildrenChanged(parentId);
266da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    }
267da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                }
268da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
269da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                @Override
270da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                public void onChildChanged(String parentId, Bundle item,
271da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                                           Drawable leftIcon, Drawable rightIcon) {
272da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    DisplayMetrics metrics = getResources().getDisplayMetrics();
273da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    if (leftIcon != null) {
274da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                        item.putParcelable(Constants.CarMenuConstants.KEY_LEFTICON,
275da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                                Utils.snapshot(metrics, leftIcon));
276da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    }
277da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
278da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    if (rightIcon != null) {
279da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                        item.putParcelable(Constants.CarMenuConstants.KEY_RIGHTICON,
280da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                                Utils.snapshot(metrics, rightIcon));
281da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    }
282da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    if (mOnCreateCalled) {
283da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                        mBinder.onChildChanged(parentId, item);
284da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    }
285da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                }
286da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            };
287da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
288da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    protected void onCreate(Bundle savedInstanceState) {
289da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        super.onCreate(savedInstanceState);
290da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        super.setContentView(mUiController.getContentView());
291da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mBinder = new CarMenuCallbacksBinder(this);
29270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        mInputManager = getInputManager();
293da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mHandler.post(new Runnable() {
294da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            @Override
295da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            public void run() {
296da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                registerCarMenuCallbacks(mBinder);
297da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                if (mMenuCallbacks != null) {
298da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    mMenuCallbacks.registerOnChildrenChangedListener(mMenuListener);
299da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                }
300da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                mOnCreateCalled = true;
301da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            }
302da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        });
303da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
304da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
305da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    protected void onDestroy() {
306da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        super.onDestroy();
307da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mHandler.post(new Runnable() {
308da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            @Override
309da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            public void run() {
310da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                if (mMenuCallbacks != null) {
311da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    mMenuCallbacks.unregisterOnChildrenChangedListener(mMenuListener);
312da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    mMenuCallbacks = null;
313da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                }
314da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            }
315da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        });
316da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
317da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
318da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    protected void onRestoreInstanceState(Bundle savedInstanceState) {
319da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        super.onRestoreInstanceState(savedInstanceState);
320da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mDrawerShowing = savedInstanceState.getBoolean(KEY_DRAWERSHOWING);
321da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mUiController.onRestoreInstanceState(savedInstanceState);
322da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
323da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
324da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    protected void onSaveInstanceState(Bundle outState) {
325da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        super.onSaveInstanceState(outState);
326da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        outState.putBoolean(KEY_DRAWERSHOWING, mDrawerShowing);
327da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mUiController.onSaveInstanceState(outState);
328da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
329da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
330da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    public void closeDrawer() {
331da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mUiController.closeDrawer();
332da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
333da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
334da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    public void openDrawer() {
335da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        mUiController.openDrawer();
336da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
337da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
33870f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    public boolean isDrawerShowing() {
33970f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        return mDrawerShowing;
34070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    }
34170f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
34270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    /**
34370f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     * Shows a small clickable {@link android.widget.EditText}.
34470f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     *
34570f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     * {@link View} will be {@code null} in {@link View.OnClickListener#onClick(View)}.
34670f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     *
34770f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     * @param listener {@link View.OnClickListener} that is called when user selects the
34870f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     *                 {@link android.widget.EditText}.
34970f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     */
35070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    public void showSearchBox(View.OnClickListener listener) {
35170f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        if (!isDrawerShowing()) {
35270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            mUiController.showSearchBox(listener);
35370f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            mShowingSearchBox = true;
35470f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        }
35570f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        mSearchBoxEnabled = true;
35670f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        mSearchBoxOnClickListener = listener;
35770f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    }
35870f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
35970f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    public void hideSearchBox() {
36070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        if (isShowingSearchBox()) {
36170f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            stopInput();
36270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        }
36370f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        mSearchBoxEnabled = false;
36470f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    }
36570f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
36670f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    public boolean isShowingSearchBox() {
36770f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        return mShowingSearchBox;
36870f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    }
36970f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
37070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    public void setSearchBoxEditListener(SearchBoxEditListener listener) {
37170f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        mUiController.setSearchBoxEditListener(new SearchBoxEditListenerBinder(listener));
37270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    }
37370f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
37470f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    public void stopInput() {
37570f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        // STOPSHIP: sometimes focus is lost and we are not able to hide the keyboard.
37670f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        // properly fix this before we ship.
37770f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        if (mSearchBoxView != null) {
37870f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            mSearchBoxView.requestFocusFromTouch();
37970f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        }
38070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        mUiController.stopInput();
38170f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        mInputManager.stopInput();
38270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        mShowingSearchBox = false;
38370f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    }
38470f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
38570f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    /**
38670f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     * Start input on the search box that is provided by a car ui provider.
38770f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     * TODO: Migrate to use the new input/search api once it becomes stable (b/27108311).
38870f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     * @param hint Search hint
38970f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     */
39070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    public void startInput(String hint) {
39170f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        startInput(hint, mSearchBoxOnClickListener);
39270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    }
39370f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
39470f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    /**
39570f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     * Start input on the search box that is provided by a car ui provider.
39670f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     * TODO: Migrate to use the new input/search api once it becomes stable (b/27108311).
39770f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     * @param hint Search hint
39870f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     * @param onClickListener Listener for the search box clicks.
39970f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen     */
40070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    public void startInput(final String hint, final View.OnClickListener onClickListener) {
40170f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        mInputManager = getInputManager();
40270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        EditText inputView = mUiController.startSearchInput(hint, onClickListener);
40370f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        getInputManager().startInput(inputView);
40470f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        mSearchBoxView = inputView;
40570f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        mShowingSearchBox = true;
40670f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    }
40770f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
40870f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    public void setSearchBoxColors(int backgroundColor, int googleLogoColor, int textColor,
40970f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            int hintTextColor) {
41070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        mUiController.setSearchBoxColors(backgroundColor, googleLogoColor, textColor, hintTextColor);
41170f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    }
41270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
41370f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    public void setSearchBoxEndView(View endView) {
41470f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        mUiController.setSearchBoxEndView(endView);
41570f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    }
41670f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
41770f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    public void showToast(String text, int duration) {
41870f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    }
41970f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
42070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    private static class SearchBoxEditListenerBinder extends ISearchBoxEditListener.Stub {
42170f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        private final SearchBoxEditListener mListener;
42270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
42370f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        public SearchBoxEditListenerBinder(SearchBoxEditListener listener) {
42470f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            if (listener == null) {
42570f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen                throw new IllegalArgumentException("Listener cannot be null");
42670f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            }
42770f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            mListener = listener;
42870f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        }
42970f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
43070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        @Override
43170f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        public void onSearch(String text) {
43270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            mListener.onSearch(text);
43370f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        }
43470f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
43570f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        @Override
43670f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        public void onEdit(String text) {
43770f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            mListener.onEdit(text);
43870f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen        }
43970f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen    }
44070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen
441da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    private static class CarMenuCallbacksBinder extends ICarMenuCallbacks.Stub {
442da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        // Map of subscribed ids to their respective callbacks.
443da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        private final Map<String, List<ISubscriptionCallbacks>> mSubscriptionMap = new HashMap<>();
444da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        private OnMenuClickListener mMenuClickListener;
445da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        private final WeakReference<CarDrawerActivity> mActivity;
446da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
447da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        CarMenuCallbacksBinder(CarDrawerActivity activity) {
448da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            mActivity = new WeakReference<>(activity);
449da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
450da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
451da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        @Override
452da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        public int getVersion() {
453da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            return 0;
454da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
455da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
456da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        @Override
457da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        public Bundle getRoot() throws RemoteException {
458da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            CarDrawerActivity activity = mActivity.get();
459da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            if (activity != null && activity.mMenuCallbacks != null) {
460da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                Root root = activity.mMenuCallbacks.onGetRoot(null);
461da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                return root.getBundle();
462da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            } else {
463da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                return null;
464da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            }
465da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
466da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
467da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        @Override
468da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        public synchronized void subscribe(final String parentId,
469da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                                           final ISubscriptionCallbacks callbacks) throws RemoteException {
470da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            if (!mSubscriptionMap.containsKey(parentId)) {
471da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                mSubscriptionMap.put(parentId, new ArrayList<ISubscriptionCallbacks>());
472da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            }
473da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            mSubscriptionMap.get(parentId).add(callbacks);
474da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            loadResultsForClient(parentId, callbacks);
475da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
476da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
477da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        @Override
478da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        public synchronized void unsubscribe(String id, ISubscriptionCallbacks callbacks)
479da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                throws RemoteException {
480da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            mSubscriptionMap.get(id).remove(callbacks);
481da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
482da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
483da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        @Override
484da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        public void onCarMenuOpened() throws RemoteException {
485da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            CarDrawerActivity activity = mActivity.get();
486da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            if (activity != null) {
487da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                activity.mDrawerShowing = true;
488da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                activity.mMenuCallbacks.onCarMenuOpened();
489da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            }
490da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
491da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
492da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
493da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        @Override
494da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        public void onCarMenuClosing() throws RemoteException {
49570f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            CarDrawerActivity activity = mActivity.get();
49670f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            if (activity != null) {
49770f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen                if (activity.mSearchBoxEnabled) {
49870f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen                    activity.mUiController.showSearchBox(activity.mSearchBoxOnClickListener);
49970f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen                    activity.mShowingSearchBox = true;
50070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen                }
50170f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            }
502da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
503da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
504da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        @Override
505da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        public void onCarMenuClosed() throws RemoteException {
506da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            CarDrawerActivity activity = mActivity.get();
50770f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            if (activity != null) {
50870f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen                activity.mDrawerShowing = false;
50970f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen                if (activity.mSearchBoxEnabled && !activity.mShowingSearchBox) {
51070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen                    activity.showSearchBox(activity.mSearchBoxOnClickListener);
51170f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen                }
51270f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            }
513da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
514da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
515da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        @Override
516da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        public void onCarMenuOpening() throws RemoteException {
517da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            CarDrawerActivity activity = mActivity.get();
51870f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            if (activity != null) {
51970f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen                activity.stopInput();
52070f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen            }
521da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
522da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
523da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        @Override
524da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        public void onItemClicked(String id) throws RemoteException {
525da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            CarDrawerActivity activity = mActivity.get();
526da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            if (activity != null) {
527da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                activity.mMenuCallbacks.onItemClicked(id);
528da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                // TODO: Add support for IME
52970f6a63ea01a15f33f282edcf31948a35b789aa7Yao Chen                activity.stopInput();
530da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            }
531da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
532da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
533da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        @Override
534da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        public boolean onItemLongClicked(String id) throws RemoteException {
535da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            CarDrawerActivity activity = mActivity.get();
536da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            if (activity != null) {
537da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                return activity.mMenuCallbacks.onItemLongClicked(id);
538da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            } else {
539da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                return false;
540da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            }
541da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
542da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
543da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        @Override
544da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        public void onStateChanged(int newState) throws RemoteException {
545da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            CarDrawerActivity activity = mActivity.get();
546da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            if (activity != null) {
547da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                activity.mMenuCallbacks.onStateChanged(newState);
548da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            }
549da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
550da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
551da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        public void setOnMenuClickedListener(OnMenuClickListener listener) {
552da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            mMenuClickListener = listener;
553da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
554da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
555da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        @Override
556da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        public boolean onMenuClicked() {
557da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            CarDrawerActivity activity = mActivity.get();
558da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            if (activity == null) {
559da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                return false;
560da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            }
561da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
562da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            if (mMenuClickListener != null) {
563da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                if (mMenuClickListener.onClicked()) {
564da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    return true;
565da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                }
566da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            }
567da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            return false;
568da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
569da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
570da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        public void onChildrenChanged(String parentId) {
571da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            if (mSubscriptionMap.containsKey(parentId)) {
572da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                loadResultsForAllClients(parentId);
573da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            }
574da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
575da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
576da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        public void reloadSubscribedMenus() {
577da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            for (String parentId : mSubscriptionMap.keySet()) {
578da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                loadResultsForAllClients(parentId);
579da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            }
580da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
581da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
582da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        private void loadResultsForClient(final String parentId,
583da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                                          final ISubscriptionCallbacks callbacks) {
584da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            CarDrawerActivity activity = mActivity.get();
585da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            if (activity == null) {
586da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                return;
587da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            }
588da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
589da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            final CarMenu result = new CarMenu(activity.getResources().getDisplayMetrics()) {
590da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                @Override
591da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                protected void onResultReady(List<Bundle> list) {
592da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    synchronized (CarMenuCallbacksBinder.this) {
593da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                        try {
594da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                            callbacks.onChildrenLoaded(parentId, list);
595da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                        } catch (RemoteException e) {
596da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                            Log.e(TAG, "Error calling onChildrenLoaded: ", e);
597da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                        }
598da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    }
599da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                }
600da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            };
601da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
602da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            activity.mMenuCallbacks.onLoadChildren(parentId, result);
603da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            if (!result.isDone()) {
604da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                throw new IllegalStateException("You must either call sendResult() or detach() " +
605da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                        "before returning!");
606da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            }
607da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
608da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
609da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        private void loadResultsForAllClients(final String parentId) {
610da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            CarDrawerActivity activity = mActivity.get();
611da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            if (activity == null) {
612da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                return;
613da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            }
614da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
615da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            final CarMenu result = new CarMenu(activity.getResources().getDisplayMetrics()) {
616da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                @Override
617da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                protected void onResultReady(List<Bundle> list) {
618da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    synchronized (CarMenuCallbacksBinder.this) {
619da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                        if (mSubscriptionMap.containsKey(parentId)) {
620da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                            try {
621da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                                for (ISubscriptionCallbacks callbacks :
622da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                                        mSubscriptionMap.get(parentId)) {
623da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                                    callbacks.onChildrenLoaded(parentId, list);
624da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                                }
625da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                            } catch (RemoteException e) {
626da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                                Log.e(TAG, "Error calling onChildrenLoaded: ", e);
627da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                            }
628da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                        }
629da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    }
630da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                }
631da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            };
632da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
633da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            activity.mMenuCallbacks.onLoadChildren(parentId, result);
634da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
635da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen
636da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        private synchronized void onChildChanged(String parentId, Bundle item) {
637da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            if (mSubscriptionMap.containsKey(parentId)) {
638da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                for (ISubscriptionCallbacks callbacks : mSubscriptionMap.get(parentId)) {
639da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    try {
640da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                        callbacks.onChildChanged(parentId, item);
641da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    } catch (RemoteException e) {
642da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                        Log.e(TAG, "Error calling onChildChanged: ", e);
643da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                    }
644da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen                }
645da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen            }
646da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen        }
647da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen    }
648da63b8de8a536a9e19c5443fcc3e2d4d2316f5eaYao Chen}
649