• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.car.cluster.sample;
17 
18 import static android.car.cluster.sample.SampleClusterServiceImpl.LOCAL_BINDING_ACTION;
19 
20 import android.car.cluster.sample.SampleClusterServiceImpl.Listener;
21 import android.content.ComponentName;
22 import android.content.Intent;
23 import android.content.ServiceConnection;
24 import android.os.Bundle;
25 import android.os.IBinder;
26 import android.util.Log;
27 import android.util.SparseArray;
28 import android.view.InputDevice;
29 import android.view.KeyEvent;
30 import android.view.View;
31 import android.view.inputmethod.InputMethodManager;
32 import android.widget.Button;
33 
34 import androidx.fragment.app.Fragment;
35 import androidx.fragment.app.FragmentActivity;
36 import androidx.fragment.app.FragmentManager;
37 import androidx.fragment.app.FragmentPagerAdapter;
38 import androidx.viewpager.widget.ViewPager;
39 
40 import java.lang.reflect.InvocationTargetException;
41 import java.util.HashMap;
42 
43 public class MainClusterActivity extends FragmentActivity
44         implements Listener {
45     private static final String TAG = MainClusterActivity.class.getSimpleName();
46 
47     private ViewPager mPager;
48 
49     private SampleClusterServiceImpl mService;
50 
51     private HashMap<Button, Facet<?>> mButtonToFacet = new HashMap<>();
52     private SparseArray<Facet<?>> mOrderToFacet = new SparseArray<>();
53 
54     private InputMethodManager mInputMethodManager;
55 
56     private final View.OnFocusChangeListener mFacetButtonFocusListener =
57             new View.OnFocusChangeListener() {
58         @Override
59         public void onFocusChange(View v, boolean hasFocus) {
60             if (hasFocus) {
61                 mPager.setCurrentItem(mButtonToFacet.get(v).order);
62             }
63         }
64     };
65 
66     @Override
onCreate(Bundle savedInstanceState)67     protected void onCreate(Bundle savedInstanceState) {
68         super.onCreate(savedInstanceState);
69         setContentView(R.layout.activity_main);
70 
71         mInputMethodManager = getSystemService(InputMethodManager.class);
72 
73         Intent intent = new Intent(this, SampleClusterServiceImpl.class);
74         intent.setAction(LOCAL_BINDING_ACTION);
75         bindService(intent,
76                 new ServiceConnection() {
77                     @Override
78                     public void onServiceConnected(ComponentName name, IBinder service) {
79                         Log.i(TAG, "onServiceConnected, name: " + name + ", service: " + service);
80                         mService = ((SampleClusterServiceImpl.LocalBinder) service)
81                                 .getService();
82                         mService.registerListener(MainClusterActivity.this);
83                     }
84 
85                     @Override
86                     public void onServiceDisconnected(ComponentName name) {
87                         Log.i(TAG, "onServiceDisconnected, name: " + name);
88                         mService = null;
89                     }
90                 }, BIND_AUTO_CREATE);
91 
92         registerFacets(
93                 new Facet<>(findViewById(R.id.btn_nav), 0, NavigationFragment.class),
94                 new Facet<>(findViewById(R.id.btn_phone), 1, PhoneFragment.class),
95                 new Facet<>(findViewById(R.id.btn_music), 2, MusicFragment.class),
96                 new Facet<>(findViewById(R.id.btn_car_info), 3, CarInfoFragment.class));
97 
98         mPager = findViewById(R.id.pager);
99         mPager.setAdapter(new ClusterPageAdapter(getSupportFragmentManager()));
100         mOrderToFacet.get(0).button.requestFocus();
101     }
102 
103     @Override
onDestroy()104     protected void onDestroy() {
105         super.onDestroy();
106         if (mService != null) {
107             mService.unregisterListener();
108         }
109     }
110 
111     @Override
onKeyEvent(KeyEvent event)112     public void onKeyEvent(KeyEvent event) {
113         Log.i(TAG, "onKeyEvent, event: " + event);
114 
115         // This is a hack. We use SOURCE_CLASS_POINTER here because this type of input is associated
116         // with the display. otherwise this event will be ignored in ViewRootImpl because injecting
117         // KeyEvent w/o activity being focused is useless.
118         event.setSource(event.getSource() | InputDevice.SOURCE_CLASS_POINTER);
119         mInputMethodManager.dispatchKeyEventFromInputMethod(getCurrentFocus(), event);
120     }
121 
122 
123     public class ClusterPageAdapter extends FragmentPagerAdapter {
ClusterPageAdapter(FragmentManager fm)124         public ClusterPageAdapter(FragmentManager fm) {
125             super(fm);
126         }
127 
128         @Override
getCount()129         public int getCount() {
130             return mButtonToFacet.size();
131         }
132 
133         @Override
getItem(int position)134         public Fragment getItem(int position) {
135             return mOrderToFacet.get(position).getOrCreateFragment();
136         }
137     }
138 
registerFacets(Facet<?>.... facets)139     private void registerFacets(Facet<?>... facets) {
140         for (Facet<?> f : facets) {
141             registerFacet(f);
142         }
143     }
144 
registerFacet(Facet<T> facet)145     private <T> void registerFacet(Facet<T> facet) {
146         mOrderToFacet.append(facet.order, facet);
147         mButtonToFacet.put(facet.button, facet);
148 
149         facet.button.setOnFocusChangeListener(mFacetButtonFocusListener);
150     }
151 
152     private static class Facet<T> {
153         Button button;
154         Class<T> clazz;
155         int order;
156 
Facet(Button button, int order, Class<T> clazz)157         Facet(Button button, int order, Class<T> clazz) {
158             this.button = button;
159             this.order = order;
160             this.clazz = clazz;
161         }
162 
163         private Fragment mFragment;
164 
getOrCreateFragment()165         Fragment getOrCreateFragment() {
166             if (mFragment == null) {
167                 try {
168                     mFragment = (Fragment) clazz.getConstructors()[0].newInstance();
169                 } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
170                     throw new RuntimeException(e);
171                 }
172             }
173             return mFragment;
174         }
175     }
176 
getService()177     SampleClusterServiceImpl getService() {
178         return mService;
179     }
180 }
181