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