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 
17 package com.android.companiondevicemanager;
18 
19 import static android.companion.BluetoothDeviceFilterUtils.getDeviceMacAddress;
20 
21 import android.app.Activity;
22 import android.companion.CompanionDeviceManager;
23 import android.content.Intent;
24 import android.content.pm.PackageManager;
25 import android.content.res.Resources;
26 import android.database.DataSetObserver;
27 import android.os.Bundle;
28 import android.text.Html;
29 import android.util.Log;
30 import android.view.Gravity;
31 import android.view.View;
32 import android.widget.ListView;
33 import android.widget.ProgressBar;
34 import android.widget.TextView;
35 
36 import com.android.companiondevicemanager.DeviceDiscoveryService.DeviceFilterPair;
37 import com.android.internal.util.Preconditions;
38 
39 public class DeviceChooserActivity extends Activity {
40 
41     private static final boolean DEBUG = false;
42     private static final String LOG_TAG = "DeviceChooserActivity";
43 
44     View mLoadingIndicator = null;
45     ListView mDeviceListView;
46     private View mPairButton;
47     private View mCancelButton;
48 
49     @Override
onCreate(Bundle savedInstanceState)50     public void onCreate(Bundle savedInstanceState) {
51         super.onCreate(savedInstanceState);
52 
53         if (DEBUG) Log.i(LOG_TAG, "Started with intent " + getIntent());
54 
55         if (getService().mDevicesFound.isEmpty()) {
56             Log.e(LOG_TAG, "About to show UI, but no devices to show");
57         }
58 
59         if (getService().mRequest.isSingleDevice()) {
60             setContentView(R.layout.device_confirmation);
61             final DeviceFilterPair selectedDevice = getService().mDevicesFound.get(0);
62             setTitle(Html.fromHtml(getString(
63                     R.string.confirmation_title,
64                     getCallingAppName(),
65                     selectedDevice.getDisplayName()), 0));
66             mPairButton = findViewById(R.id.button_pair);
67             mPairButton.setOnClickListener(v -> onDeviceConfirmed(getService().mSelectedDevice));
68             getService().mSelectedDevice = selectedDevice;
69             onSelectionUpdate();
70         } else {
71             setContentView(R.layout.device_chooser);
72             mPairButton = findViewById(R.id.button_pair);
73             mPairButton.setVisibility(View.GONE);
74             setTitle(Html.fromHtml(getString(R.string.chooser_title, getCallingAppName()), 0));
75             mDeviceListView = findViewById(R.id.device_list);
76             final DeviceDiscoveryService.DevicesAdapter adapter = getService().mDevicesAdapter;
77             mDeviceListView.setAdapter(adapter);
78             adapter.registerDataSetObserver(new DataSetObserver() {
79                 @Override
80                 public void onChanged() {
81                     onSelectionUpdate();
82                 }
83             });
84             mDeviceListView.addFooterView(mLoadingIndicator = getProgressBar(), null, false);
85         }
86         getService().mActivity = this;
87 
88         mCancelButton = findViewById(R.id.button_cancel);
89         mCancelButton.setOnClickListener(v -> cancel());
90     }
91 
cancel()92     private void cancel() {
93         getService().onCancel();
94         setResult(RESULT_CANCELED);
95         finish();
96     }
97 
98     @Override
onStop()99     protected void onStop() {
100         super.onStop();
101         if (!isFinishing() && !isChangingConfigurations()) {
102             cancel();
103         }
104     }
105 
getCallingAppName()106     private CharSequence getCallingAppName() {
107         try {
108             final PackageManager packageManager = getPackageManager();
109             String callingPackage = Preconditions.checkStringNotEmpty(
110                     getCallingPackage(),
111                     "This activity must be called for result");
112             return packageManager.getApplicationLabel(
113                     packageManager.getApplicationInfo(callingPackage, 0));
114         } catch (PackageManager.NameNotFoundException e) {
115             throw new RuntimeException(e);
116         }
117     }
118 
119     @Override
setTitle(CharSequence title)120     public void setTitle(CharSequence title) {
121         final TextView titleView = findViewById(R.id.title);
122         final int padding = getPadding(getResources());
123         titleView.setPadding(padding, padding, padding, padding);
124         titleView.setText(title);
125     }
126 
127     //TODO put in resources xmls
getProgressBar()128     private ProgressBar getProgressBar() {
129         final ProgressBar progressBar = new ProgressBar(this);
130         progressBar.setForegroundGravity(Gravity.CENTER_HORIZONTAL);
131         final int padding = getPadding(getResources());
132         progressBar.setPadding(padding, padding, padding, padding);
133         return progressBar;
134     }
135 
getPadding(Resources r)136     static int getPadding(Resources r) {
137         return r.getDimensionPixelSize(R.dimen.padding);
138     }
139 
onSelectionUpdate()140     private void onSelectionUpdate() {
141         DeviceFilterPair selectedDevice = getService().mSelectedDevice;
142         if (mPairButton.getVisibility() != View.VISIBLE && selectedDevice != null) {
143             onDeviceConfirmed(selectedDevice);
144         } else {
145             mPairButton.setEnabled(selectedDevice != null);
146         }
147     }
148 
getService()149     private DeviceDiscoveryService getService() {
150         return DeviceDiscoveryService.sInstance;
151     }
152 
onDeviceConfirmed(DeviceFilterPair selectedDevice)153    protected void onDeviceConfirmed(DeviceFilterPair selectedDevice) {
154         getService().onDeviceSelected(
155                 getCallingPackage(), getDeviceMacAddress(selectedDevice.device));
156         setResult(RESULT_OK,
157                 new Intent().putExtra(CompanionDeviceManager.EXTRA_DEVICE, selectedDevice.device));
158         finish();
159     }
160 }