• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 com.android.car.carlauncher;
17 
18 import android.annotation.Nullable;
19 import android.app.Activity;
20 import android.car.Car;
21 import android.car.CarNotConnectedException;
22 import android.car.content.pm.CarPackageManager;
23 import android.car.drivingstate.CarUxRestrictionsManager;
24 import android.content.BroadcastReceiver;
25 import android.content.ComponentName;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.IntentFilter;
29 import android.content.ServiceConnection;
30 import android.content.pm.LauncherApps;
31 import android.content.pm.PackageManager;
32 import android.os.Bundle;
33 import android.os.IBinder;
34 import android.text.Editable;
35 import android.text.TextUtils;
36 import android.text.TextWatcher;
37 import android.util.Log;
38 import android.view.View;
39 import android.view.inputmethod.InputMethodManager;
40 import android.widget.EditText;
41 
42 import androidx.recyclerview.widget.RecyclerView;
43 import java.util.Collections;
44 import java.util.List;
45 
46 /**
47  * Activity that allows user to search in apps.
48  */
49 public final class AppSearchActivity extends Activity {
50 
51     private static final String TAG = "AppSearchActivity";
52 
53     private PackageManager mPackageManager;
54     private SearchResultAdapter mSearchResultAdapter;
55     private AppInstallUninstallReceiver mInstallUninstallReceiver;
56     private Car mCar;
57     private CarPackageManager mCarPackageManager;
58     private CarUxRestrictionsManager mCarUxRestrictionsManager;
59 
60     private ServiceConnection mCarConnectionListener = new ServiceConnection() {
61         @Override
62         public void onServiceConnected(ComponentName name, IBinder service) {
63             try {
64                 mCarUxRestrictionsManager = (CarUxRestrictionsManager) mCar.getCarManager(
65                         Car.CAR_UX_RESTRICTION_SERVICE);
66                 mSearchResultAdapter.setIsDistractionOptimizationRequired(
67                         mCarUxRestrictionsManager
68                                 .getCurrentCarUxRestrictions()
69                                 .isRequiresDistractionOptimization());
70                 mCarUxRestrictionsManager.registerListener(
71                         restrictionInfo ->
72                                 mSearchResultAdapter.setIsDistractionOptimizationRequired(
73                                         restrictionInfo.isRequiresDistractionOptimization()));
74 
75                 mCarPackageManager = (CarPackageManager) mCar.getCarManager(Car.PACKAGE_SERVICE);
76                 mSearchResultAdapter.setAllApps(getAllApps());
77             } catch (CarNotConnectedException e) {
78                 Log.e(TAG, "Car not connected in CarConnectionListener", e);
79             }
80         }
81 
82         @Override
83         public void onServiceDisconnected(ComponentName name) {
84             mCarUxRestrictionsManager = null;
85             mCarPackageManager = null;
86         }
87     };
88 
89     @Override
onCreate(@ullable Bundle savedInstanceState)90     protected void onCreate(@Nullable Bundle savedInstanceState) {
91         super.onCreate(savedInstanceState);
92         mPackageManager = getPackageManager();
93         mCar = Car.createCar(this, mCarConnectionListener);
94 
95         setContentView(R.layout.app_search_activity);
96         findViewById(R.id.container).setOnTouchListener(
97                 (view, event) -> {
98                     hideKeyboard();
99                     return false;
100                 });
101         findViewById(R.id.exit_button_container).setOnClickListener(view -> finish());
102 
103         RecyclerView searchResultView = findViewById(R.id.search_result);
104         searchResultView.setClipToOutline(true);
105         mSearchResultAdapter = new SearchResultAdapter(this);
106         searchResultView.setAdapter(mSearchResultAdapter);
107 
108         EditText searchBar = findViewById(R.id.app_search_bar);
109         searchBar.addTextChangedListener(new TextWatcher() {
110             @Override
111             public void beforeTextChanged(CharSequence s, int start, int count, int after) {
112             }
113 
114             @Override
115             public void onTextChanged(CharSequence s, int start, int before, int count) {
116             }
117 
118             @Override
119             public void afterTextChanged(Editable s) {
120                 if (TextUtils.isEmpty(s)) {
121                     searchResultView.setVisibility(View.GONE);
122                     mSearchResultAdapter.clearResults();
123                 } else {
124                     searchResultView.setVisibility(View.VISIBLE);
125                     mSearchResultAdapter.getFilter().filter(s.toString());
126                 }
127             }
128         });
129     }
130 
131     @Override
onStart()132     protected void onStart() {
133         super.onStart();
134         // register broadcast receiver for package installation and uninstallation
135         mInstallUninstallReceiver = new AppInstallUninstallReceiver();
136         IntentFilter filter = new IntentFilter();
137         filter.addAction(Intent.ACTION_PACKAGE_ADDED);
138         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
139         filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
140         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
141         filter.addDataScheme("package");
142         registerReceiver(mInstallUninstallReceiver, filter);
143 
144         // Connect to car service
145         mCar.connect();
146     }
147 
148     @Override
onStop()149     protected void onStop() {
150         super.onPause();
151         // disconnect from app install/uninstall receiver
152         if (mInstallUninstallReceiver != null) {
153             unregisterReceiver(mInstallUninstallReceiver);
154             mInstallUninstallReceiver = null;
155         }
156         // disconnect from car listeners
157         try {
158             if (mCarUxRestrictionsManager != null) {
159                 mCarUxRestrictionsManager.unregisterListener();
160             }
161         } catch (CarNotConnectedException e) {
162             Log.e(TAG, "Error unregistering listeners", e);
163         }
164         if (mCar != null) {
165             mCar.disconnect();
166         }
167     }
168 
getAllApps()169     private List<AppMetaData> getAllApps() {
170         AppLauncherUtils.LauncherAppsInfo appsInfo = AppLauncherUtils.getAllLauncherApps(
171                 Collections.emptySet(), getSystemService(LauncherApps.class), mCarPackageManager,
172                 mPackageManager);
173         return appsInfo.getApplicationsList();
174     }
175 
hideKeyboard()176     public void hideKeyboard() {
177         InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(
178                 Activity.INPUT_METHOD_SERVICE);
179         inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
180     }
181 
182     private class AppInstallUninstallReceiver extends BroadcastReceiver {
183         @Override
onReceive(Context context, Intent intent)184         public void onReceive(Context context, Intent intent) {
185             String packageName = intent.getData().getSchemeSpecificPart();
186 
187             if (TextUtils.isEmpty(packageName)) {
188                 Log.e(TAG, "System sent an empty app install/uninstall broadcast");
189                 return;
190             }
191 
192             mSearchResultAdapter.setAllApps(getAllApps());
193         }
194     }
195 }
196