Roberto Perez | 004455c | 2019-08-23 17:18:37 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2019 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 | */ |
Roberto Perez | feec33c | 2019-09-19 16:23:22 -0700 | [diff] [blame] | 16 | |
Brad Stenning | 298e58b | 2019-09-12 15:29:54 -0700 | [diff] [blame] | 17 | package com.android.car.ui.paintbooth; |
Roberto Perez | 004455c | 2019-08-23 17:18:37 -0700 | [diff] [blame] | 18 | |
| 19 | import android.app.Activity; |
Cole Faust | bdbee87 | 2019-12-06 12:47:08 -0800 | [diff] [blame] | 20 | import android.app.ActivityManager; |
Cole Faust | f8d7c74 | 2020-04-01 16:02:52 -0700 | [diff] [blame] | 21 | import android.app.Service; |
Cole Faust | bdbee87 | 2019-12-06 12:47:08 -0800 | [diff] [blame] | 22 | import android.content.Context; |
Roberto Perez | 004455c | 2019-08-23 17:18:37 -0700 | [diff] [blame] | 23 | import android.content.Intent; |
| 24 | import android.os.Bundle; |
Cole Faust | e264476 | 2019-12-06 10:56:43 -0800 | [diff] [blame] | 25 | import android.util.Log; |
Roberto Perez | fcbe6f5 | 2019-09-11 08:13:12 -0700 | [diff] [blame] | 26 | import android.view.LayoutInflater; |
| 27 | import android.view.View; |
| 28 | import android.view.ViewGroup; |
Roberto Perez | 004455c | 2019-08-23 17:18:37 -0700 | [diff] [blame] | 29 | import android.widget.Button; |
Cole Faust | bdbee87 | 2019-12-06 12:47:08 -0800 | [diff] [blame] | 30 | import android.widget.Switch; |
Cole Faust | e264476 | 2019-12-06 10:56:43 -0800 | [diff] [blame] | 31 | import android.widget.Toast; |
Roberto Perez | 004455c | 2019-08-23 17:18:37 -0700 | [diff] [blame] | 32 | |
Roberto Perez | fcbe6f5 | 2019-09-11 08:13:12 -0700 | [diff] [blame] | 33 | import androidx.annotation.NonNull; |
| 34 | import androidx.recyclerview.widget.RecyclerView; |
| 35 | |
Cole Faust | b30c388 | 2020-02-25 14:26:50 -0800 | [diff] [blame] | 36 | import com.android.car.ui.baselayout.Insets; |
| 37 | import com.android.car.ui.baselayout.InsetsChangedListener; |
| 38 | import com.android.car.ui.core.CarUi; |
Ram Parameswaran | fa84da1 | 2019-10-31 09:57:35 -0700 | [diff] [blame] | 39 | import com.android.car.ui.paintbooth.caruirecyclerview.CarUiListItemActivity; |
Priyank Singh | 7361b4b | 2019-10-04 11:24:10 -0700 | [diff] [blame] | 40 | import com.android.car.ui.paintbooth.caruirecyclerview.CarUiRecyclerViewActivity; |
| 41 | import com.android.car.ui.paintbooth.caruirecyclerview.GridCarUiRecyclerViewActivity; |
Cole Faust | 0503424 | 2019-12-23 14:40:37 -0800 | [diff] [blame] | 42 | import com.android.car.ui.paintbooth.currentactivity.CurrentActivityService; |
Roberto Perez | feec33c | 2019-09-19 16:23:22 -0700 | [diff] [blame] | 43 | import com.android.car.ui.paintbooth.dialogs.DialogsActivity; |
Roberto Perez | 638196f | 2019-10-11 17:24:34 -0700 | [diff] [blame] | 44 | import com.android.car.ui.paintbooth.overlays.OverlayActivity; |
Roberto Perez | feec33c | 2019-09-19 16:23:22 -0700 | [diff] [blame] | 45 | import com.android.car.ui.paintbooth.preferences.PreferenceActivity; |
Priyank Singh | 36bd38d | 2020-03-20 16:50:12 -0700 | [diff] [blame] | 46 | import com.android.car.ui.paintbooth.toolbar.NoCarUiToolbarActivity; |
Cole Faust | 92f3066 | 2020-05-21 12:12:22 -0700 | [diff] [blame] | 47 | import com.android.car.ui.paintbooth.toolbar.OldToolbarActivity; |
Cole Faust | f87980d | 2019-09-20 10:23:22 -0700 | [diff] [blame] | 48 | import com.android.car.ui.paintbooth.toolbar.ToolbarActivity; |
Priyank Singh | 440572d | 2019-10-15 09:56:59 -0700 | [diff] [blame] | 49 | import com.android.car.ui.paintbooth.widgets.WidgetActivity; |
Priyank Singh | 7361b4b | 2019-10-04 11:24:10 -0700 | [diff] [blame] | 50 | import com.android.car.ui.recyclerview.CarUiRecyclerView; |
Cole Faust | b30c388 | 2020-02-25 14:26:50 -0800 | [diff] [blame] | 51 | import com.android.car.ui.toolbar.ToolbarController; |
Roberto Perez | fcbe6f5 | 2019-09-11 08:13:12 -0700 | [diff] [blame] | 52 | |
Cole Faust | e264476 | 2019-12-06 10:56:43 -0800 | [diff] [blame] | 53 | import java.lang.reflect.Method; |
Roberto Perez | fcbe6f5 | 2019-09-11 08:13:12 -0700 | [diff] [blame] | 54 | import java.util.Arrays; |
| 55 | import java.util.List; |
| 56 | |
Roberto Perez | 004455c | 2019-08-23 17:18:37 -0700 | [diff] [blame] | 57 | /** |
| 58 | * Paint booth app |
| 59 | */ |
Cole Faust | b30c388 | 2020-02-25 14:26:50 -0800 | [diff] [blame] | 60 | public class MainActivity extends Activity implements InsetsChangedListener { |
Priyank Singh | cedf1d2 | 2019-10-04 12:34:14 -0700 | [diff] [blame] | 61 | |
Cole Faust | f8d7c74 | 2020-04-01 16:02:52 -0700 | [diff] [blame] | 62 | public static final String STOP_SERVICE = "com.android.car.ui.paintbooth.StopService"; |
| 63 | |
Roberto Perez | fcbe6f5 | 2019-09-11 08:13:12 -0700 | [diff] [blame] | 64 | /** |
| 65 | * List of all sample activities. |
| 66 | */ |
Cole Faust | f8d7c74 | 2020-04-01 16:02:52 -0700 | [diff] [blame] | 67 | private final List<ListElement> mActivities = Arrays.asList( |
| 68 | new ServiceElement("Show foreground activities", CurrentActivityService.class), |
| 69 | new ServiceElement("Simulate Screen Bounds", VisibleBoundsSimulator.class), |
| 70 | new ActivityElement("Dialogs sample", DialogsActivity.class), |
| 71 | new ActivityElement("List sample", CarUiRecyclerViewActivity.class), |
| 72 | new ActivityElement("Grid sample", GridCarUiRecyclerViewActivity.class), |
| 73 | new ActivityElement("Preferences sample", PreferenceActivity.class), |
| 74 | new ActivityElement("Overlays", OverlayActivity.class), |
| 75 | new ActivityElement("Toolbar sample", ToolbarActivity.class), |
Cole Faust | 92f3066 | 2020-05-21 12:12:22 -0700 | [diff] [blame] | 76 | new ActivityElement("Old toolbar sample", OldToolbarActivity.class), |
Cole Faust | f8d7c74 | 2020-04-01 16:02:52 -0700 | [diff] [blame] | 77 | new ActivityElement("No CarUiToolbar sample", NoCarUiToolbarActivity.class), |
| 78 | new ActivityElement("Widget sample", WidgetActivity.class), |
Cole Faust | 92f3066 | 2020-05-21 12:12:22 -0700 | [diff] [blame] | 79 | new ActivityElement("ListItem sample", CarUiListItemActivity.class)); |
Cole Faust | bdbee87 | 2019-12-06 12:47:08 -0800 | [diff] [blame] | 80 | |
Cole Faust | f8d7c74 | 2020-04-01 16:02:52 -0700 | [diff] [blame] | 81 | private abstract static class ViewHolder extends RecyclerView.ViewHolder { |
Roberto Perez | fcbe6f5 | 2019-09-11 08:13:12 -0700 | [diff] [blame] | 82 | |
| 83 | ViewHolder(@NonNull View itemView) { |
| 84 | super(itemView); |
Cole Faust | f8d7c74 | 2020-04-01 16:02:52 -0700 | [diff] [blame] | 85 | } |
| 86 | |
| 87 | public abstract void bind(ListElement element); |
| 88 | } |
| 89 | |
| 90 | private class ActivityViewHolder extends ViewHolder { |
Cole Faust | 95e316e | 2020-04-02 17:09:40 -0700 | [diff] [blame] | 91 | private final Button mButton; |
Cole Faust | f8d7c74 | 2020-04-01 16:02:52 -0700 | [diff] [blame] | 92 | |
| 93 | ActivityViewHolder(@NonNull View itemView) { |
| 94 | super(itemView); |
Cole Faust | 95e316e | 2020-04-02 17:09:40 -0700 | [diff] [blame] | 95 | mButton = itemView.requireViewById(R.id.button); |
Roberto Perez | fcbe6f5 | 2019-09-11 08:13:12 -0700 | [diff] [blame] | 96 | } |
| 97 | |
Cole Faust | f8d7c74 | 2020-04-01 16:02:52 -0700 | [diff] [blame] | 98 | @Override |
| 99 | public void bind(ListElement e) { |
| 100 | if (!(e instanceof ActivityElement)) { |
| 101 | throw new IllegalArgumentException("Expected an ActivityElement"); |
Cole Faust | bdbee87 | 2019-12-06 12:47:08 -0800 | [diff] [blame] | 102 | } |
Cole Faust | f8d7c74 | 2020-04-01 16:02:52 -0700 | [diff] [blame] | 103 | ActivityElement element = (ActivityElement) e; |
| 104 | mButton.setText(element.getText()); |
| 105 | mButton.setOnClickListener(v -> |
| 106 | startActivity(new Intent(itemView.getContext(), element.getActivity()))); |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | private class ServiceViewHolder extends ViewHolder { |
Cole Faust | 95e316e | 2020-04-02 17:09:40 -0700 | [diff] [blame] | 111 | private final Switch mSwitch; |
Cole Faust | f8d7c74 | 2020-04-01 16:02:52 -0700 | [diff] [blame] | 112 | |
| 113 | ServiceViewHolder(@NonNull View itemView) { |
| 114 | super(itemView); |
Cole Faust | 95e316e | 2020-04-02 17:09:40 -0700 | [diff] [blame] | 115 | mSwitch = itemView.requireViewById(R.id.button); |
Cole Faust | f8d7c74 | 2020-04-01 16:02:52 -0700 | [diff] [blame] | 116 | } |
| 117 | |
| 118 | @Override |
| 119 | public void bind(ListElement e) { |
| 120 | if (!(e instanceof ServiceElement)) { |
| 121 | throw new IllegalArgumentException("Expected an ActivityElement"); |
| 122 | } |
| 123 | ServiceElement element = (ServiceElement) e; |
| 124 | mSwitch.setChecked(isServiceRunning(element.getService())); |
| 125 | mSwitch.setText(element.getText()); |
| 126 | mSwitch.setOnClickListener(v -> { |
| 127 | Intent intent = new Intent(itemView.getContext(), element.getService()); |
| 128 | if (isServiceRunning(element.getService())) { |
| 129 | intent.setAction(STOP_SERVICE); |
| 130 | } |
| 131 | startForegroundService(intent); |
| 132 | }); |
Roberto Perez | fcbe6f5 | 2019-09-11 08:13:12 -0700 | [diff] [blame] | 133 | } |
| 134 | } |
| 135 | |
Roberto Perez | 638196f | 2019-10-11 17:24:34 -0700 | [diff] [blame] | 136 | private final RecyclerView.Adapter<ViewHolder> mAdapter = |
| 137 | new RecyclerView.Adapter<ViewHolder>() { |
Cole Faust | bdbee87 | 2019-12-06 12:47:08 -0800 | [diff] [blame] | 138 | @NonNull |
| 139 | @Override |
| 140 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { |
Cole Faust | f8d7c74 | 2020-04-01 16:02:52 -0700 | [diff] [blame] | 141 | LayoutInflater inflater = LayoutInflater.from(parent.getContext()); |
| 142 | if (viewType == ListElement.TYPE_ACTIVITY) { |
| 143 | return new ActivityViewHolder( |
| 144 | inflater.inflate(R.layout.list_item, parent, false)); |
| 145 | } else if (viewType == ListElement.TYPE_SERVICE) { |
| 146 | return new ServiceViewHolder( |
| 147 | inflater.inflate(R.layout.list_item_switch, parent, false)); |
| 148 | } else { |
| 149 | throw new IllegalArgumentException("Unknown viewType: " + viewType); |
| 150 | } |
Cole Faust | bdbee87 | 2019-12-06 12:47:08 -0800 | [diff] [blame] | 151 | } |
| 152 | |
| 153 | @Override |
| 154 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) { |
Cole Faust | f8d7c74 | 2020-04-01 16:02:52 -0700 | [diff] [blame] | 155 | holder.bind(mActivities.get(position)); |
Cole Faust | bdbee87 | 2019-12-06 12:47:08 -0800 | [diff] [blame] | 156 | } |
| 157 | |
| 158 | @Override |
| 159 | public int getItemCount() { |
Priyank Singh | c2e159b | 2020-03-27 12:14:48 -0700 | [diff] [blame] | 160 | return mActivities.size(); |
Cole Faust | bdbee87 | 2019-12-06 12:47:08 -0800 | [diff] [blame] | 161 | } |
| 162 | |
| 163 | @Override |
| 164 | public int getItemViewType(int position) { |
Cole Faust | f8d7c74 | 2020-04-01 16:02:52 -0700 | [diff] [blame] | 165 | return mActivities.get(position).getType(); |
Cole Faust | bdbee87 | 2019-12-06 12:47:08 -0800 | [diff] [blame] | 166 | } |
| 167 | }; |
Roberto Perez | fcbe6f5 | 2019-09-11 08:13:12 -0700 | [diff] [blame] | 168 | |
Roberto Perez | 004455c | 2019-08-23 17:18:37 -0700 | [diff] [blame] | 169 | @Override |
| 170 | protected void onCreate(Bundle savedInstanceState) { |
| 171 | super.onCreate(savedInstanceState); |
Cole Faust | b30c388 | 2020-02-25 14:26:50 -0800 | [diff] [blame] | 172 | setContentView(R.layout.car_ui_recycler_view_activity); |
Roberto Perez | 004455c | 2019-08-23 17:18:37 -0700 | [diff] [blame] | 173 | |
Cole Faust | b30c388 | 2020-02-25 14:26:50 -0800 | [diff] [blame] | 174 | ToolbarController toolbar = CarUi.requireToolbar(this); |
| 175 | toolbar.setLogo(R.drawable.ic_launcher); |
| 176 | toolbar.setTitle(getTitle()); |
| 177 | |
| 178 | CarUiRecyclerView prv = findViewById(R.id.list); |
Roberto Perez | fcbe6f5 | 2019-09-11 08:13:12 -0700 | [diff] [blame] | 179 | prv.setAdapter(mAdapter); |
Cole Faust | e264476 | 2019-12-06 10:56:43 -0800 | [diff] [blame] | 180 | |
| 181 | initLeakCanary(); |
| 182 | } |
| 183 | |
| 184 | private void initLeakCanary() { |
| 185 | // This sets LeakCanary to report errors after a single leak instead of 5, and to ask for |
| 186 | // permission to use storage, which it needs to work. |
| 187 | // |
| 188 | // Equivalent to this non-reflection code: |
| 189 | // |
| 190 | // Config config = LeakCanary.INSTANCE.getConfig(); |
| 191 | // LeakCanary.INSTANCE.setConfig(config.copy(config.getDumpHeap(), |
| 192 | // config.getDumpHeapWhenDebugging(), |
| 193 | // 1, |
| 194 | // config.getReferenceMatchers(), |
| 195 | // config.getObjectInspectors(), |
| 196 | // config.getOnHeapAnalyzedListener(), |
| 197 | // config.getMetatadaExtractor(), |
| 198 | // config.getComputeRetainedHeapSize(), |
| 199 | // config.getMaxStoredHeapDumps(), |
| 200 | // true, |
| 201 | // config.getUseExperimentalLeakFinders())); |
| 202 | try { |
| 203 | Class<?> canaryClass = Class.forName("leakcanary.LeakCanary"); |
| 204 | try { |
| 205 | Class<?> onHeapAnalyzedListenerClass = |
| 206 | Class.forName("leakcanary.OnHeapAnalyzedListener"); |
| 207 | Class<?> metadataExtractorClass = Class.forName("shark.MetadataExtractor"); |
| 208 | Method getConfig = canaryClass.getMethod("getConfig"); |
| 209 | Class<?> configClass = getConfig.getReturnType(); |
| 210 | Method setConfig = canaryClass.getMethod("setConfig", configClass); |
| 211 | Method copy = configClass.getMethod("copy", boolean.class, boolean.class, |
| 212 | int.class, List.class, List.class, onHeapAnalyzedListenerClass, |
| 213 | metadataExtractorClass, boolean.class, int.class, boolean.class, |
| 214 | boolean.class); |
| 215 | |
| 216 | Object canary = canaryClass.getField("INSTANCE").get(null); |
| 217 | Object currentConfig = getConfig.invoke(canary); |
| 218 | |
| 219 | Boolean dumpHeap = (Boolean) configClass |
| 220 | .getMethod("getDumpHeap").invoke(currentConfig); |
| 221 | Boolean dumpHeapWhenDebugging = (Boolean) configClass |
| 222 | .getMethod("getDumpHeapWhenDebugging").invoke(currentConfig); |
Cole Faust | ac23e8b | 2019-12-05 11:33:09 -0800 | [diff] [blame] | 223 | List<?> referenceMatchers = (List<?>) configClass |
Cole Faust | e264476 | 2019-12-06 10:56:43 -0800 | [diff] [blame] | 224 | .getMethod("getReferenceMatchers").invoke(currentConfig); |
Cole Faust | ac23e8b | 2019-12-05 11:33:09 -0800 | [diff] [blame] | 225 | List<?> objectInspectors = (List<?>) configClass |
Cole Faust | e264476 | 2019-12-06 10:56:43 -0800 | [diff] [blame] | 226 | .getMethod("getObjectInspectors").invoke(currentConfig); |
| 227 | Object onHeapAnalyzedListener = configClass |
| 228 | .getMethod("getOnHeapAnalyzedListener").invoke(currentConfig); |
| 229 | // Yes, LeakCanary misspelled metadata |
| 230 | Object metadataExtractor = configClass |
| 231 | .getMethod("getMetatadaExtractor").invoke(currentConfig); |
| 232 | Boolean computeRetainedHeapSize = (Boolean) configClass |
| 233 | .getMethod("getComputeRetainedHeapSize").invoke(currentConfig); |
| 234 | Integer maxStoredHeapDumps = (Integer) configClass |
| 235 | .getMethod("getMaxStoredHeapDumps").invoke(currentConfig); |
| 236 | Boolean useExperimentalLeakFinders = (Boolean) configClass |
| 237 | .getMethod("getUseExperimentalLeakFinders").invoke(currentConfig); |
| 238 | |
| 239 | setConfig.invoke(canary, copy.invoke(currentConfig, |
| 240 | dumpHeap, |
| 241 | dumpHeapWhenDebugging, |
| 242 | 1, |
| 243 | referenceMatchers, |
| 244 | objectInspectors, |
| 245 | onHeapAnalyzedListener, |
| 246 | metadataExtractor, |
| 247 | computeRetainedHeapSize, |
| 248 | maxStoredHeapDumps, |
| 249 | true, |
| 250 | useExperimentalLeakFinders)); |
| 251 | |
| 252 | } catch (ReflectiveOperationException e) { |
| 253 | Log.e("paintbooth", "Error initializing LeakCanary", e); |
| 254 | Toast.makeText(this, "Error initializing LeakCanary", Toast.LENGTH_LONG).show(); |
| 255 | } |
| 256 | } catch (ClassNotFoundException e) { |
| 257 | // LeakCanary is not used in this build, do nothing. |
| 258 | } |
Roberto Perez | 004455c | 2019-08-23 17:18:37 -0700 | [diff] [blame] | 259 | } |
Cole Faust | bdbee87 | 2019-12-06 12:47:08 -0800 | [diff] [blame] | 260 | |
Cole Faust | f8d7c74 | 2020-04-01 16:02:52 -0700 | [diff] [blame] | 261 | private boolean isServiceRunning(Class<? extends Service> serviceClazz) { |
Cole Faust | bdbee87 | 2019-12-06 12:47:08 -0800 | [diff] [blame] | 262 | ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); |
| 263 | for (ActivityManager.RunningServiceInfo service : manager.getRunningServices( |
| 264 | Integer.MAX_VALUE)) { |
Priyank Singh | c2e159b | 2020-03-27 12:14:48 -0700 | [diff] [blame] | 265 | if (serviceClazz.getName().equals(service.service.getClassName())) { |
Cole Faust | bdbee87 | 2019-12-06 12:47:08 -0800 | [diff] [blame] | 266 | return true; |
| 267 | } |
| 268 | } |
| 269 | return false; |
| 270 | } |
Cole Faust | b30c388 | 2020-02-25 14:26:50 -0800 | [diff] [blame] | 271 | |
| 272 | @Override |
Ram Parameswaran | d2f51b7 | 2020-06-05 14:30:56 -0700 | [diff] [blame] | 273 | public void onCarUiInsetsChanged(@NonNull Insets insets) { |
Cole Faust | b30c388 | 2020-02-25 14:26:50 -0800 | [diff] [blame] | 274 | requireViewById(R.id.list) |
| 275 | .setPadding(0, insets.getTop(), 0, insets.getBottom()); |
| 276 | requireViewById(android.R.id.content) |
| 277 | .setPadding(insets.getLeft(), 0, insets.getRight(), 0); |
| 278 | } |
Priyank Singh | c2e159b | 2020-03-27 12:14:48 -0700 | [diff] [blame] | 279 | |
Cole Faust | f8d7c74 | 2020-04-01 16:02:52 -0700 | [diff] [blame] | 280 | private abstract static class ListElement { |
| 281 | static final int TYPE_ACTIVITY = 0; |
| 282 | static final int TYPE_SERVICE = 1; |
Priyank Singh | c2e159b | 2020-03-27 12:14:48 -0700 | [diff] [blame] | 283 | |
Cole Faust | f8d7c74 | 2020-04-01 16:02:52 -0700 | [diff] [blame] | 284 | private final String mText; |
| 285 | |
| 286 | ListElement(String text) { |
| 287 | mText = text; |
| 288 | } |
| 289 | |
| 290 | String getText() { |
| 291 | return mText; |
| 292 | } |
| 293 | |
| 294 | abstract int getType(); |
| 295 | } |
| 296 | |
| 297 | private static class ActivityElement extends ListElement { |
| 298 | private final Class<? extends Activity> mActivityClass; |
| 299 | |
| 300 | ActivityElement(String text, Class<? extends Activity> activityClass) { |
| 301 | super(text); |
| 302 | mActivityClass = activityClass; |
| 303 | } |
| 304 | |
| 305 | Class<? extends Activity> getActivity() { |
| 306 | return mActivityClass; |
| 307 | } |
| 308 | |
| 309 | @Override |
| 310 | int getType() { |
| 311 | return TYPE_ACTIVITY; |
| 312 | } |
| 313 | } |
| 314 | |
| 315 | private static class ServiceElement extends ListElement { |
| 316 | private final Class<? extends Service> mServiceClass; |
| 317 | |
| 318 | ServiceElement(String text, Class<? extends Service> serviceClass) { |
| 319 | super(text); |
| 320 | mServiceClass = serviceClass; |
| 321 | } |
| 322 | |
| 323 | Class<? extends Service> getService() { |
| 324 | return mServiceClass; |
| 325 | } |
| 326 | |
| 327 | @Override |
| 328 | int getType() { |
| 329 | return TYPE_SERVICE; |
Priyank Singh | c2e159b | 2020-03-27 12:14:48 -0700 | [diff] [blame] | 330 | } |
| 331 | } |
Roberto Perez | 004455c | 2019-08-23 17:18:37 -0700 | [diff] [blame] | 332 | } |