1 /* 2 * Copyright (C) 2024 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.settings.connecteddevice.virtual; 18 19 import android.companion.virtual.VirtualDevice; 20 import android.companion.virtual.VirtualDeviceManager; 21 import android.content.Context; 22 import android.graphics.drawable.Icon; 23 import android.view.View; 24 import android.widget.ImageView; 25 import android.widget.TextView; 26 27 import androidx.annotation.NonNull; 28 import androidx.annotation.Nullable; 29 import androidx.lifecycle.Lifecycle; 30 import androidx.lifecycle.LifecycleObserver; 31 import androidx.lifecycle.OnLifecycleEvent; 32 import androidx.preference.PreferenceScreen; 33 34 import com.android.settings.R; 35 import com.android.settings.core.BasePreferenceController; 36 import com.android.settingslib.widget.LayoutPreference; 37 38 import java.util.Objects; 39 import java.util.concurrent.Executor; 40 import java.util.concurrent.Executors; 41 42 /** This class adds a header for a virtual device with a heading and icon. */ 43 public class VirtualDeviceDetailsHeaderController extends BasePreferenceController implements 44 LifecycleObserver, VirtualDeviceManager.VirtualDeviceListener { 45 46 private static final String KEY_VIRTUAL_DEVICE_DETAILS_HEADER = "virtual_device_details_header"; 47 48 @Nullable 49 private final VirtualDeviceManager mVirtualDeviceManager; 50 @Nullable 51 private VirtualDeviceWrapper mDevice; 52 @Nullable 53 private TextView mSummaryView; 54 55 private final Executor mExecutor = Executors.newSingleThreadExecutor(); 56 VirtualDeviceDetailsHeaderController(@onNull Context context)57 public VirtualDeviceDetailsHeaderController(@NonNull Context context) { 58 super(context, KEY_VIRTUAL_DEVICE_DETAILS_HEADER); 59 mVirtualDeviceManager = 60 Objects.requireNonNull(context.getSystemService(VirtualDeviceManager.class)); 61 } 62 63 /** One-time initialization when the controller is first created. */ init(@onNull VirtualDeviceWrapper device)64 void init(@NonNull VirtualDeviceWrapper device) { 65 mDevice = device; 66 } 67 68 @OnLifecycleEvent(Lifecycle.Event.ON_START) onStart()69 void onStart() { 70 if (mVirtualDeviceManager != null) { 71 mVirtualDeviceManager.registerVirtualDeviceListener(mExecutor, this); 72 } 73 } 74 75 @OnLifecycleEvent(Lifecycle.Event.ON_STOP) onStop()76 void onStop() { 77 if (mVirtualDeviceManager != null) { 78 mVirtualDeviceManager.unregisterVirtualDeviceListener(this); 79 } 80 } 81 82 @Override onVirtualDeviceCreated(int deviceId)83 public void onVirtualDeviceCreated(int deviceId) { 84 VirtualDevice device = 85 Objects.requireNonNull(mVirtualDeviceManager).getVirtualDevice(deviceId); 86 if (mDevice != null && device != null 87 && mDevice.getPersistentDeviceId().equals(device.getPersistentDeviceId())) { 88 mDevice.setDeviceId(deviceId); 89 mContext.getMainExecutor().execute(this::updateSummary); 90 } 91 } 92 93 @Override onVirtualDeviceClosed(int deviceId)94 public void onVirtualDeviceClosed(int deviceId) { 95 if (mDevice != null && deviceId == mDevice.getDeviceId()) { 96 mDevice.setDeviceId(Context.DEVICE_ID_INVALID); 97 mContext.getMainExecutor().execute(this::updateSummary); 98 } 99 } 100 101 @Override displayPreference(@onNull PreferenceScreen screen)102 public void displayPreference(@NonNull PreferenceScreen screen) { 103 super.displayPreference(screen); 104 LayoutPreference headerPreference = screen.findPreference(getPreferenceKey()); 105 View view = headerPreference.findViewById(R.id.entity_header); 106 TextView titleView = view.findViewById(R.id.entity_header_title); 107 ImageView iconView = headerPreference.findViewById(R.id.entity_header_icon); 108 mSummaryView = view.findViewById(R.id.entity_header_summary); 109 updateSummary(); 110 if (mDevice != null) { 111 titleView.setText(mDevice.getDeviceName(mContext)); 112 Icon deviceIcon = android.companion.Flags.associationDeviceIcon() 113 ? mDevice.getAssociationInfo().getDeviceIcon() : null; 114 if (deviceIcon == null) { 115 iconView.setImageResource(R.drawable.ic_devices_other); 116 } else { 117 iconView.setImageIcon(deviceIcon); 118 } 119 } 120 } 121 updateSummary()122 private void updateSummary() { 123 if (mSummaryView != null && mDevice != null) { 124 mSummaryView.setText(mDevice.getDeviceId() != Context.DEVICE_ID_INVALID 125 ? R.string.virtual_device_connected : R.string.virtual_device_disconnected); 126 } 127 } 128 129 @Override getAvailabilityStatus()130 public int getAvailabilityStatus() { 131 return AVAILABLE; 132 } 133 } 134