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