Loading packages/CompanionDeviceManager/AndroidManifest.xml +1 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,7 @@ android:supportsRtl="true"> <activity android:name=".CompanionDeviceActivity" android:name=".CompanionAssociationActivity" android:exported="true" android:launchMode="singleInstance" android:excludeFromRecents="true" Loading packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java→packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java +58 −108 Original line number Diff line number Diff line Loading @@ -65,7 +65,7 @@ import android.os.Handler; import android.os.RemoteException; import android.os.ResultReceiver; import android.text.Spanned; import android.util.Log; import android.util.Slog; import android.view.View; import android.view.ViewTreeObserver; import android.view.accessibility.AccessibilityNodeInfo; Loading @@ -91,9 +91,8 @@ import java.util.List; * nearby devices to be associated with. */ @SuppressLint("LongLogTag") public class CompanionDeviceActivity extends FragmentActivity implements public class CompanionAssociationActivity extends FragmentActivity implements CompanionVendorHelperDialogFragment.CompanionVendorHelperDialogListener { private static final boolean DEBUG = false; private static final String TAG = "CDM_CompanionDeviceActivity"; // Keep the following constants in sync with Loading Loading @@ -183,11 +182,11 @@ public class CompanionDeviceActivity extends FragmentActivity implements @Override public void onCreate(Bundle savedInstanceState) { if (DEBUG) Log.d(TAG, "onCreate()"); boolean forceCancelDialog = getIntent().getBooleanExtra("cancel_confirmation", false); boolean forceCancelDialog = getIntent().getBooleanExtra(EXTRA_FORCE_CANCEL_CONFIRMATION, false); // Must handle the force cancel request in onNewIntent. if (forceCancelDialog) { Log.i(TAG, "The confirmation does not exist, skipping the cancel request"); Slog.i(TAG, "The confirmation does not exist, skipping the cancel request"); finish(); } Loading @@ -198,13 +197,13 @@ public class CompanionDeviceActivity extends FragmentActivity implements @Override protected void onStart() { super.onStart(); if (DEBUG) Log.d(TAG, "onStart()"); final Intent intent = getIntent(); mRequest = intent.getParcelableExtra(EXTRA_ASSOCIATION_REQUEST); mRequest = intent.getParcelableExtra(EXTRA_ASSOCIATION_REQUEST, AssociationRequest.class); mAppCallback = IAssociationRequestCallback.Stub.asInterface( intent.getExtras().getBinder(EXTRA_APPLICATION_CALLBACK)); mCdmServiceReceiver = intent.getParcelableExtra(EXTRA_RESULT_RECEIVER); mCdmServiceReceiver = intent.getParcelableExtra(EXTRA_RESULT_RECEIVER, ResultReceiver.class); requireNonNull(mRequest); requireNonNull(mAppCallback); Loading @@ -221,29 +220,22 @@ public class CompanionDeviceActivity extends FragmentActivity implements initUI(); } @SuppressWarnings("MissingSuperCall") // TODO: Fix me @Override protected void onNewIntent(Intent intent) { protected void onNewIntent(@NonNull Intent intent) { super.onNewIntent(intent); // Force cancels the CDM dialog if this activity receives another intent with // EXTRA_FORCE_CANCEL_CONFIRMATION. boolean forCancelDialog = intent.getBooleanExtra(EXTRA_FORCE_CANCEL_CONFIRMATION, false); if (forCancelDialog) { Log.i(TAG, "Cancelling the user confirmation"); cancel(/* discoveryTimeOut */ false, /* userRejected */ false, /* internalError */ false); Slog.i(TAG, "Cancelling the user confirmation"); cancel(/* discoveryTimeOut */ false, /* userRejected */ false, /* internalError */ false); return; } // Handle another incoming request (while we are not done with the original - mRequest - // yet). final AssociationRequest request = requireNonNull( intent.getParcelableExtra(EXTRA_ASSOCIATION_REQUEST)); if (DEBUG) Log.d(TAG, "onNewIntent(), request=" + request); // We can only "process" one request at a time. // yet). We can only "process" one request at a time. final IAssociationRequestCallback appCallback = IAssociationRequestCallback.Stub .asInterface(intent.getExtras().getBinder(EXTRA_APPLICATION_CALLBACK)); try { Loading @@ -255,7 +247,6 @@ public class CompanionDeviceActivity extends FragmentActivity implements @Override protected void onStop() { super.onStop(); if (DEBUG) Log.d(TAG, "onStop(), finishing=" + isFinishing()); // TODO: handle config changes without cancelling. if (!isDone()) { Loading @@ -264,26 +255,8 @@ public class CompanionDeviceActivity extends FragmentActivity implements } } @Override protected void onDestroy() { super.onDestroy(); if (DEBUG) Log.d(TAG, "onDestroy()"); } @Override public void onBackPressed() { if (DEBUG) Log.d(TAG, "onBackPressed()"); super.onBackPressed(); } @Override public void finish() { if (DEBUG) Log.d(TAG, "finish()", new Exception("Stack Trace Dump")); super.finish(); } private void initUI() { if (DEBUG) Log.d(TAG, "initUI(), request=" + mRequest); Slog.d(TAG, "initUI(), request=" + mRequest); final String packageName = mRequest.getPackageName(); final int userId = mRequest.getUserId(); Loading @@ -292,7 +265,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements try { appLabel = getApplicationLabel(this, packageName, userId); } catch (PackageManager.NameNotFoundException e) { Log.w(TAG, "Package u" + userId + "/" + packageName + " not found."); Slog.w(TAG, "Package u" + userId + "/" + packageName + " not found."); CompanionDeviceDiscoveryService.stop(this); setResultAndFinish(null, RESULT_INTERNAL_ERROR); Loading Loading @@ -341,9 +314,9 @@ public class CompanionDeviceActivity extends FragmentActivity implements if (mRequest.isSelfManaged()) { initUiForSelfManagedAssociation(); } else if (mRequest.isSingleDevice()) { initUiForSingleDevice(appLabel); initUiForSingleDevice(); } else { initUiForMultipleDevices(appLabel); initUiForMultipleDevices(); } } Loading @@ -364,12 +337,12 @@ public class CompanionDeviceActivity extends FragmentActivity implements private void onAssociationApproved(@Nullable MacAddress macAddress) { if (isDone()) { if (DEBUG) Log.w(TAG, "Already done: " + (mApproved ? "Approved" : "Cancelled")); Slog.w(TAG, "Already done: " + (mApproved ? "Approved" : "Cancelled")); return; } mApproved = true; if (DEBUG) Log.i(TAG, "onAssociationApproved() macAddress=" + macAddress); Slog.i(TAG, "onAssociationApproved() macAddress=" + macAddress); if (!mRequest.isSelfManaged()) { requireNonNull(macAddress); Loading @@ -390,17 +363,8 @@ public class CompanionDeviceActivity extends FragmentActivity implements } private void cancel(boolean discoveryTimeout, boolean userRejected, boolean internalError) { if (DEBUG) { Log.i(TAG, "cancel(), discoveryTimeout=" + discoveryTimeout + ", userRejected=" + userRejected + ", internalError=" + internalError, new Exception("Stack Trace Dump")); } if (isDone()) { if (DEBUG) Log.w(TAG, "Already done: " + (mApproved ? "Approved" : "Cancelled")); Slog.w(TAG, "Already done: " + (mApproved ? "Approved" : "Cancelled")); return; } mCancelled = true; Loading Loading @@ -428,6 +392,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements // First send callback to the app directly... try { Slog.i(TAG, "Sending onFailure to app due to reason=" + cancelReason); mAppCallback.onFailure(cancelReason); } catch (RemoteException ignore) { } Loading @@ -437,7 +402,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements } private void setResultAndFinish(@Nullable AssociationInfo association, int resultCode) { Log.i(TAG, "setResultAndFinish(), association=" Slog.i(TAG, "setResultAndFinish(), association=" + (association == null ? "null" : association) + "resultCode=" + resultCode); Loading @@ -454,7 +419,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements } private void initUiForSelfManagedAssociation() { if (DEBUG) Log.i(TAG, "initUiFor_SelfManaged_Association()"); Slog.d(TAG, "initUiForSelfManagedAssociation()"); final CharSequence deviceName = mRequest.getDisplayName(); final String deviceProfile = mRequest.getDeviceProfile(); Loading @@ -477,7 +442,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements mVendorHeaderImage.setColorFilter(getResources().getColor(color, /* Theme= */null)); } } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, "Package u" + userId + "/" + packageName + " not found."); Slog.e(TAG, "Package u" + userId + "/" + packageName + " not found."); cancel(/* discoveryTimeout */ false, /* userRejected */ false, /* internalError */ true); return; Loading Loading @@ -506,8 +471,8 @@ public class CompanionDeviceActivity extends FragmentActivity implements mBorderBottom.setVisibility(View.GONE); } private void initUiForSingleDevice(CharSequence appLabel) { if (DEBUG) Log.i(TAG, "initUiFor_SingleDevice()"); private void initUiForSingleDevice() { Slog.d(TAG, "initUiForSingleDevice()"); final String deviceProfile = mRequest.getDeviceProfile(); Loading @@ -515,9 +480,16 @@ public class CompanionDeviceActivity extends FragmentActivity implements throw new RuntimeException("Unsupported profile " + deviceProfile); } CompanionDeviceDiscoveryService.getScanResult().observe(this, deviceFilterPairs -> updateSingleDeviceUi( deviceFilterPairs, deviceProfile, appLabel)); final Drawable profileIcon = getIcon(this, PROFILE_ICONS.get(deviceProfile)); mProfileIcon.setImageDrawable(profileIcon); CompanionDeviceDiscoveryService.getScanResult().observe(this, deviceFilterPairs -> { if (deviceFilterPairs.isEmpty()) { return; } mSelectedDevice = requireNonNull(deviceFilterPairs.get(0)); updateSingleDeviceUi(); }); mSingleDeviceSpinner.setVisibility(View.VISIBLE); // Hide permission list and confirmation dialog first before the Loading @@ -527,33 +499,8 @@ public class CompanionDeviceActivity extends FragmentActivity implements mAssociationConfirmationDialog.setVisibility(View.GONE); } private void updateSingleDeviceUi(List<DeviceFilterPair<?>> deviceFilterPairs, String deviceProfile, CharSequence appLabel) { // Ignore "empty" scan reports. if (deviceFilterPairs.isEmpty()) return; mSelectedDevice = requireNonNull(deviceFilterPairs.get(0)); final Drawable profileIcon = getIcon(this, PROFILE_ICONS.get(deviceProfile)); // No need to show permission consent dialog if it is a isSkipPrompt(true) // AssociationRequest. See AssociationRequestsProcessor#mayAssociateWithoutPrompt. if (mRequest.isSkipPrompt()) { Log.d(TAG, "Skipping the permission consent dialog."); mSingleDeviceSpinner.setVisibility(View.GONE); onUserSelectedDevice(mSelectedDevice); return; } updatePermissionUi(); mProfileIcon.setImageDrawable(profileIcon); mAssociationConfirmationDialog.setVisibility(View.VISIBLE); mSingleDeviceSpinner.setVisibility(View.GONE); } private void initUiForMultipleDevices(CharSequence appLabel) { if (DEBUG) Log.i(TAG, "initUiFor_MultipleDevices()"); private void initUiForMultipleDevices() { Slog.d(TAG, "initUiForMultipleDevices()"); final Drawable profileIcon; final Spanned title; Loading @@ -566,7 +513,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements profileIcon = getIcon(this, PROFILE_ICONS.get(deviceProfile)); if (deviceProfile == null) { title = getHtmlFromResources(this, R.string.chooser_title_non_profile, appLabel); title = getHtmlFromResources(this, R.string.chooser_title_non_profile, mAppLabel); mButtonNotAllowMultipleDevices.setText(R.string.consent_no); } else { title = getHtmlFromResources(this, Loading Loading @@ -606,7 +553,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements final DeviceFilterPair<?> selectedDevice = mDeviceAdapter.getItem(position); // To prevent double tap on the selected device. if (mSelectedDevice != null) { if (DEBUG) Log.w(TAG, "Already selected."); Slog.w(TAG, "Already selected."); return; } // Notify the adapter to highlight the selected item. Loading @@ -614,17 +561,9 @@ public class CompanionDeviceActivity extends FragmentActivity implements mSelectedDevice = requireNonNull(selectedDevice); Log.d(TAG, "onDeviceClicked(): " + mSelectedDevice.toShortString()); Slog.d(TAG, "onDeviceClicked(): " + mSelectedDevice.toShortString()); // No need to show permission consent dialog if it is a isSkipPrompt(true) // AssociationRequest. See AssociationRequestsProcessor#mayAssociateWithoutPrompt. if (mRequest.isSkipPrompt()) { Log.d(TAG, "Skipping the permission consent dialog."); onUserSelectedDevice(mSelectedDevice); return; } updatePermissionUi(); updateSingleDeviceUi(); mSummary.setVisibility(View.VISIBLE); mButtonAllow.setVisibility(View.VISIBLE); Loading @@ -633,7 +572,18 @@ public class CompanionDeviceActivity extends FragmentActivity implements mNotAllowMultipleDevicesLayout.setVisibility(View.GONE); } private void updatePermissionUi() { private void updateSingleDeviceUi() { // No need to show permission consent dialog if it is a isSkipPrompt(true) // AssociationRequest. See AssociationRequestsProcessor#mayAssociateWithoutPrompt. if (mRequest.isSkipPrompt()) { Slog.d(TAG, "Skipping the permission consent dialog."); onUserSelectedDevice(mSelectedDevice); return; } mSingleDeviceSpinner.setVisibility(View.GONE); mAssociationConfirmationDialog.setVisibility(View.VISIBLE); final String deviceProfile = mRequest.getDeviceProfile(); final int summaryResourceId = PROFILE_SUMMARIES.get(deviceProfile); final String remoteDeviceName = mSelectedDevice.getDisplayName(); Loading @@ -658,7 +608,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements } private void onPositiveButtonClick(View v) { if (DEBUG) Log.d(TAG, "on_Positive_ButtonClick()"); Slog.d(TAG, "onPositiveButtonClick()"); // Disable the button, to prevent more clicks. v.setEnabled(false); Loading @@ -671,7 +621,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements } private void onNegativeButtonClick(View v) { if (DEBUG) Log.d(TAG, "on_Negative_ButtonClick()"); Slog.d(TAG, "onNegativeButtonClick()"); // Disable the button, to prevent more clicks. v.setEnabled(false); Loading packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java +10 −40 Original line number Diff line number Diff line Loading @@ -55,7 +55,7 @@ import android.os.IBinder; import android.os.Parcelable; import android.os.SystemProperties; import android.text.TextUtils; import android.util.Log; import android.util.Slog; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; Loading @@ -71,7 +71,6 @@ import java.util.Objects; */ @SuppressLint("LongLogTag") public class CompanionDeviceDiscoveryService extends Service { private static final boolean DEBUG = false; private static final String TAG = "CDM_CompanionDeviceDiscoveryService"; private static final String SYS_PROP_DEBUG_TIMEOUT = "debug.cdm.discovery_timeout"; Loading Loading @@ -147,7 +146,6 @@ public class CompanionDeviceDiscoveryService extends Service { @Override public void onCreate() { super.onCreate(); if (DEBUG) Log.d(TAG, "onCreate()"); mBtManager = getSystemService(BluetoothManager.class); mBtAdapter = mBtManager.getAdapter(); Loading @@ -158,7 +156,6 @@ public class CompanionDeviceDiscoveryService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { final String action = intent.getAction(); if (DEBUG) Log.d(TAG, "onStartCommand() action=" + action); switch (action) { case ACTION_START_DISCOVERY: Loading @@ -174,15 +171,9 @@ public class CompanionDeviceDiscoveryService extends Service { return START_NOT_STICKY; } @Override public void onDestroy() { super.onDestroy(); if (DEBUG) Log.d(TAG, "onDestroy()"); } @MainThread private void startDiscovery(@NonNull AssociationRequest request) { if (DEBUG) Log.i(TAG, "startDiscovery() request=" + request); Slog.d(TAG, "startDiscovery() request=" + request); requireNonNull(request); if (mDiscoveryStarted) throw new RuntimeException("Discovery in progress."); Loading Loading @@ -218,7 +209,7 @@ public class CompanionDeviceDiscoveryService extends Service { @MainThread private void stopDiscoveryAndFinish(boolean timeout) { if (DEBUG) Log.i(TAG, "stopDiscovery()"); Slog.d(TAG, "stopDiscoveryAndFinish(" + timeout + ")"); if (!mDiscoveryStarted) { stopSelf(); Loading Loading @@ -298,10 +289,9 @@ public class CompanionDeviceDiscoveryService extends Service { private BluetoothBroadcastReceiver startBtScanningIfNeeded( List<BluetoothDeviceFilter> filters, boolean force) { if (isEmpty(filters) && !force) return null; if (DEBUG) Log.d(TAG, "registerReceiver(BluetoothDevice.ACTION_FOUND)"); Slog.d(TAG, "registerReceiver(BluetoothDevice.ACTION_FOUND)"); final BluetoothBroadcastReceiver receiver = new BluetoothBroadcastReceiver(filters); final IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(receiver, intentFilter); Loading @@ -313,7 +303,7 @@ public class CompanionDeviceDiscoveryService extends Service { private WifiBroadcastReceiver startWifiScanningIfNeeded( List<WifiDeviceFilter> filters, boolean force) { if (isEmpty(filters) && !force) return null; if (DEBUG) Log.d(TAG, "registerReceiver(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)"); Slog.d(TAG, "registerReceiver(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)"); final WifiBroadcastReceiver receiver = new WifiBroadcastReceiver(filters); Loading @@ -329,10 +319,10 @@ public class CompanionDeviceDiscoveryService extends Service { private ScanCallback startBleScanningIfNeeded( List<BluetoothLeDeviceFilter> filters, boolean force) { if (isEmpty(filters) && !force) return null; if (DEBUG) Log.d(TAG, "BLEScanner.startScan"); Slog.d(TAG, "BLEScanner.startScan"); if (mBleScanner == null) { Log.w(TAG, "BLE Scanner is not available."); Slog.w(TAG, "BLE Scanner is not available."); return null; } Loading @@ -350,18 +340,13 @@ public class CompanionDeviceDiscoveryService extends Service { private void onDeviceFound(@NonNull DeviceFilterPair<?> device) { runOnMainThread(() -> { if (DEBUG) Log.v(TAG, "onDeviceFound() " + device); if (mDiscoveryStopped) return; if (mDevicesFound.contains(device)) { // TODO: update the device instead of ignoring (new found device may contain // additional/updated info, eg. name of the device). if (DEBUG) { Log.d(TAG, "onDeviceFound() " + device.toShortString() + " - Already seen: ignore."); } return; } Log.i(TAG, "onDeviceFound() " + device.toShortString() + " - New device."); Slog.i(TAG, "onDeviceFound() " + device.toShortString() + " - New device."); // First: make change. mDevicesFound.add(device); Loading @@ -376,7 +361,7 @@ public class CompanionDeviceDiscoveryService extends Service { private void onDeviceLost(@NonNull DeviceFilterPair<?> device) { runOnMainThread(() -> { Log.i(TAG, "onDeviceLost(), device=" + device.toShortString()); Slog.i(TAG, "onDeviceLost(), device=" + device.toShortString()); // First: make change. mDevicesFound.remove(device); Loading @@ -395,13 +380,10 @@ public class CompanionDeviceDiscoveryService extends Service { timeout = max(timeout, TIMEOUT_MIN); // should be >= 1 sec (TIMEOUT_MIN) } if (DEBUG) Log.d(TAG, "scheduleTimeout(), timeout=" + timeout); Handler.getMain().postDelayed(mTimeoutRunnable, timeout); } private void timeout() { if (DEBUG) Log.i(TAG, "timeout()"); stopDiscoveryAndFinish(/* timeout */ true); } Loading @@ -419,10 +401,6 @@ public class CompanionDeviceDiscoveryService extends Service { @Override public void onScanResult(int callbackType, ScanResult result) { if (DEBUG) { Log.v(TAG, "BLE.onScanResult() callback=" + callbackType + ", result=" + result); } final DeviceFilterPair<ScanResult> match = findMatch(result, mFilters); if (match == null) return; Loading @@ -447,8 +425,6 @@ public class CompanionDeviceDiscoveryService extends Service { final String action = intent.getAction(); final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (DEBUG) Log.v(TAG, action + ", device=" + device); if (action == null) return; final DeviceFilterPair<BluetoothDevice> match = findMatch(device, mFilters); Loading Loading @@ -477,10 +453,6 @@ public class CompanionDeviceDiscoveryService extends Service { } final List<android.net.wifi.ScanResult> scanResults = mWifiManager.getScanResults(); if (DEBUG) { Log.v(TAG, "WifiManager.SCAN_RESULTS_AVAILABLE_ACTION, results:\n " + TextUtils.join("\n ", scanResults)); } for (int i = 0; i < scanResults.size(); i++) { final android.net.wifi.ScanResult scanResult = scanResults.get(i); Loading @@ -505,9 +477,7 @@ public class CompanionDeviceDiscoveryService extends Service { DeviceFilterPair<T> result = matchingFilter != null ? new DeviceFilterPair<>(dev, matchingFilter) : null; if (DEBUG) { Log.v(TAG, "findMatch(dev=" + dev + ", filters=" + filters + ") -> " + result); } return result; } } services/companion/java/com/android/server/companion/association/AssociationRequestsProcessor.java +5 −5 Original line number Diff line number Diff line Loading @@ -130,7 +130,7 @@ public class AssociationRequestsProcessor { private final @NonNull PackageManagerInternal mPackageManagerInternal; private final @NonNull AssociationStore mAssociationStore; @NonNull private final ComponentName mCompanionDeviceActivity; private final ComponentName mCompanionAssociationActivity; public AssociationRequestsProcessor(@NonNull Context context, @NonNull PackageManagerInternal packageManagerInternal, Loading @@ -138,9 +138,9 @@ public class AssociationRequestsProcessor { mContext = context; mPackageManagerInternal = packageManagerInternal; mAssociationStore = associationStore; mCompanionDeviceActivity = createRelative( mCompanionAssociationActivity = createRelative( mContext.getString(R.string.config_companionDeviceManagerPackage), ".CompanionDeviceActivity"); ".CompanionAssociationActivity"); } /** Loading Loading @@ -204,7 +204,7 @@ public class AssociationRequestsProcessor { extras.putParcelable(EXTRA_RESULT_RECEIVER, prepareForIpc(mOnRequestConfirmationReceiver)); final Intent intent = new Intent(); intent.setComponent(mCompanionDeviceActivity); intent.setComponent(mCompanionAssociationActivity); intent.putExtras(extras); // 2b.3. Create a PendingIntent. Loading Loading @@ -232,7 +232,7 @@ public class AssociationRequestsProcessor { extras.putBoolean(EXTRA_FORCE_CANCEL_CONFIRMATION, true); final Intent intent = new Intent(); intent.setComponent(mCompanionDeviceActivity); intent.setComponent(mCompanionAssociationActivity); intent.putExtras(extras); return createPendingIntent(packageUid, intent); Loading Loading
packages/CompanionDeviceManager/AndroidManifest.xml +1 −1 Original line number Diff line number Diff line Loading @@ -41,7 +41,7 @@ android:supportsRtl="true"> <activity android:name=".CompanionDeviceActivity" android:name=".CompanionAssociationActivity" android:exported="true" android:launchMode="singleInstance" android:excludeFromRecents="true" Loading
packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java→packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java +58 −108 Original line number Diff line number Diff line Loading @@ -65,7 +65,7 @@ import android.os.Handler; import android.os.RemoteException; import android.os.ResultReceiver; import android.text.Spanned; import android.util.Log; import android.util.Slog; import android.view.View; import android.view.ViewTreeObserver; import android.view.accessibility.AccessibilityNodeInfo; Loading @@ -91,9 +91,8 @@ import java.util.List; * nearby devices to be associated with. */ @SuppressLint("LongLogTag") public class CompanionDeviceActivity extends FragmentActivity implements public class CompanionAssociationActivity extends FragmentActivity implements CompanionVendorHelperDialogFragment.CompanionVendorHelperDialogListener { private static final boolean DEBUG = false; private static final String TAG = "CDM_CompanionDeviceActivity"; // Keep the following constants in sync with Loading Loading @@ -183,11 +182,11 @@ public class CompanionDeviceActivity extends FragmentActivity implements @Override public void onCreate(Bundle savedInstanceState) { if (DEBUG) Log.d(TAG, "onCreate()"); boolean forceCancelDialog = getIntent().getBooleanExtra("cancel_confirmation", false); boolean forceCancelDialog = getIntent().getBooleanExtra(EXTRA_FORCE_CANCEL_CONFIRMATION, false); // Must handle the force cancel request in onNewIntent. if (forceCancelDialog) { Log.i(TAG, "The confirmation does not exist, skipping the cancel request"); Slog.i(TAG, "The confirmation does not exist, skipping the cancel request"); finish(); } Loading @@ -198,13 +197,13 @@ public class CompanionDeviceActivity extends FragmentActivity implements @Override protected void onStart() { super.onStart(); if (DEBUG) Log.d(TAG, "onStart()"); final Intent intent = getIntent(); mRequest = intent.getParcelableExtra(EXTRA_ASSOCIATION_REQUEST); mRequest = intent.getParcelableExtra(EXTRA_ASSOCIATION_REQUEST, AssociationRequest.class); mAppCallback = IAssociationRequestCallback.Stub.asInterface( intent.getExtras().getBinder(EXTRA_APPLICATION_CALLBACK)); mCdmServiceReceiver = intent.getParcelableExtra(EXTRA_RESULT_RECEIVER); mCdmServiceReceiver = intent.getParcelableExtra(EXTRA_RESULT_RECEIVER, ResultReceiver.class); requireNonNull(mRequest); requireNonNull(mAppCallback); Loading @@ -221,29 +220,22 @@ public class CompanionDeviceActivity extends FragmentActivity implements initUI(); } @SuppressWarnings("MissingSuperCall") // TODO: Fix me @Override protected void onNewIntent(Intent intent) { protected void onNewIntent(@NonNull Intent intent) { super.onNewIntent(intent); // Force cancels the CDM dialog if this activity receives another intent with // EXTRA_FORCE_CANCEL_CONFIRMATION. boolean forCancelDialog = intent.getBooleanExtra(EXTRA_FORCE_CANCEL_CONFIRMATION, false); if (forCancelDialog) { Log.i(TAG, "Cancelling the user confirmation"); cancel(/* discoveryTimeOut */ false, /* userRejected */ false, /* internalError */ false); Slog.i(TAG, "Cancelling the user confirmation"); cancel(/* discoveryTimeOut */ false, /* userRejected */ false, /* internalError */ false); return; } // Handle another incoming request (while we are not done with the original - mRequest - // yet). final AssociationRequest request = requireNonNull( intent.getParcelableExtra(EXTRA_ASSOCIATION_REQUEST)); if (DEBUG) Log.d(TAG, "onNewIntent(), request=" + request); // We can only "process" one request at a time. // yet). We can only "process" one request at a time. final IAssociationRequestCallback appCallback = IAssociationRequestCallback.Stub .asInterface(intent.getExtras().getBinder(EXTRA_APPLICATION_CALLBACK)); try { Loading @@ -255,7 +247,6 @@ public class CompanionDeviceActivity extends FragmentActivity implements @Override protected void onStop() { super.onStop(); if (DEBUG) Log.d(TAG, "onStop(), finishing=" + isFinishing()); // TODO: handle config changes without cancelling. if (!isDone()) { Loading @@ -264,26 +255,8 @@ public class CompanionDeviceActivity extends FragmentActivity implements } } @Override protected void onDestroy() { super.onDestroy(); if (DEBUG) Log.d(TAG, "onDestroy()"); } @Override public void onBackPressed() { if (DEBUG) Log.d(TAG, "onBackPressed()"); super.onBackPressed(); } @Override public void finish() { if (DEBUG) Log.d(TAG, "finish()", new Exception("Stack Trace Dump")); super.finish(); } private void initUI() { if (DEBUG) Log.d(TAG, "initUI(), request=" + mRequest); Slog.d(TAG, "initUI(), request=" + mRequest); final String packageName = mRequest.getPackageName(); final int userId = mRequest.getUserId(); Loading @@ -292,7 +265,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements try { appLabel = getApplicationLabel(this, packageName, userId); } catch (PackageManager.NameNotFoundException e) { Log.w(TAG, "Package u" + userId + "/" + packageName + " not found."); Slog.w(TAG, "Package u" + userId + "/" + packageName + " not found."); CompanionDeviceDiscoveryService.stop(this); setResultAndFinish(null, RESULT_INTERNAL_ERROR); Loading Loading @@ -341,9 +314,9 @@ public class CompanionDeviceActivity extends FragmentActivity implements if (mRequest.isSelfManaged()) { initUiForSelfManagedAssociation(); } else if (mRequest.isSingleDevice()) { initUiForSingleDevice(appLabel); initUiForSingleDevice(); } else { initUiForMultipleDevices(appLabel); initUiForMultipleDevices(); } } Loading @@ -364,12 +337,12 @@ public class CompanionDeviceActivity extends FragmentActivity implements private void onAssociationApproved(@Nullable MacAddress macAddress) { if (isDone()) { if (DEBUG) Log.w(TAG, "Already done: " + (mApproved ? "Approved" : "Cancelled")); Slog.w(TAG, "Already done: " + (mApproved ? "Approved" : "Cancelled")); return; } mApproved = true; if (DEBUG) Log.i(TAG, "onAssociationApproved() macAddress=" + macAddress); Slog.i(TAG, "onAssociationApproved() macAddress=" + macAddress); if (!mRequest.isSelfManaged()) { requireNonNull(macAddress); Loading @@ -390,17 +363,8 @@ public class CompanionDeviceActivity extends FragmentActivity implements } private void cancel(boolean discoveryTimeout, boolean userRejected, boolean internalError) { if (DEBUG) { Log.i(TAG, "cancel(), discoveryTimeout=" + discoveryTimeout + ", userRejected=" + userRejected + ", internalError=" + internalError, new Exception("Stack Trace Dump")); } if (isDone()) { if (DEBUG) Log.w(TAG, "Already done: " + (mApproved ? "Approved" : "Cancelled")); Slog.w(TAG, "Already done: " + (mApproved ? "Approved" : "Cancelled")); return; } mCancelled = true; Loading Loading @@ -428,6 +392,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements // First send callback to the app directly... try { Slog.i(TAG, "Sending onFailure to app due to reason=" + cancelReason); mAppCallback.onFailure(cancelReason); } catch (RemoteException ignore) { } Loading @@ -437,7 +402,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements } private void setResultAndFinish(@Nullable AssociationInfo association, int resultCode) { Log.i(TAG, "setResultAndFinish(), association=" Slog.i(TAG, "setResultAndFinish(), association=" + (association == null ? "null" : association) + "resultCode=" + resultCode); Loading @@ -454,7 +419,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements } private void initUiForSelfManagedAssociation() { if (DEBUG) Log.i(TAG, "initUiFor_SelfManaged_Association()"); Slog.d(TAG, "initUiForSelfManagedAssociation()"); final CharSequence deviceName = mRequest.getDisplayName(); final String deviceProfile = mRequest.getDeviceProfile(); Loading @@ -477,7 +442,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements mVendorHeaderImage.setColorFilter(getResources().getColor(color, /* Theme= */null)); } } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, "Package u" + userId + "/" + packageName + " not found."); Slog.e(TAG, "Package u" + userId + "/" + packageName + " not found."); cancel(/* discoveryTimeout */ false, /* userRejected */ false, /* internalError */ true); return; Loading Loading @@ -506,8 +471,8 @@ public class CompanionDeviceActivity extends FragmentActivity implements mBorderBottom.setVisibility(View.GONE); } private void initUiForSingleDevice(CharSequence appLabel) { if (DEBUG) Log.i(TAG, "initUiFor_SingleDevice()"); private void initUiForSingleDevice() { Slog.d(TAG, "initUiForSingleDevice()"); final String deviceProfile = mRequest.getDeviceProfile(); Loading @@ -515,9 +480,16 @@ public class CompanionDeviceActivity extends FragmentActivity implements throw new RuntimeException("Unsupported profile " + deviceProfile); } CompanionDeviceDiscoveryService.getScanResult().observe(this, deviceFilterPairs -> updateSingleDeviceUi( deviceFilterPairs, deviceProfile, appLabel)); final Drawable profileIcon = getIcon(this, PROFILE_ICONS.get(deviceProfile)); mProfileIcon.setImageDrawable(profileIcon); CompanionDeviceDiscoveryService.getScanResult().observe(this, deviceFilterPairs -> { if (deviceFilterPairs.isEmpty()) { return; } mSelectedDevice = requireNonNull(deviceFilterPairs.get(0)); updateSingleDeviceUi(); }); mSingleDeviceSpinner.setVisibility(View.VISIBLE); // Hide permission list and confirmation dialog first before the Loading @@ -527,33 +499,8 @@ public class CompanionDeviceActivity extends FragmentActivity implements mAssociationConfirmationDialog.setVisibility(View.GONE); } private void updateSingleDeviceUi(List<DeviceFilterPair<?>> deviceFilterPairs, String deviceProfile, CharSequence appLabel) { // Ignore "empty" scan reports. if (deviceFilterPairs.isEmpty()) return; mSelectedDevice = requireNonNull(deviceFilterPairs.get(0)); final Drawable profileIcon = getIcon(this, PROFILE_ICONS.get(deviceProfile)); // No need to show permission consent dialog if it is a isSkipPrompt(true) // AssociationRequest. See AssociationRequestsProcessor#mayAssociateWithoutPrompt. if (mRequest.isSkipPrompt()) { Log.d(TAG, "Skipping the permission consent dialog."); mSingleDeviceSpinner.setVisibility(View.GONE); onUserSelectedDevice(mSelectedDevice); return; } updatePermissionUi(); mProfileIcon.setImageDrawable(profileIcon); mAssociationConfirmationDialog.setVisibility(View.VISIBLE); mSingleDeviceSpinner.setVisibility(View.GONE); } private void initUiForMultipleDevices(CharSequence appLabel) { if (DEBUG) Log.i(TAG, "initUiFor_MultipleDevices()"); private void initUiForMultipleDevices() { Slog.d(TAG, "initUiForMultipleDevices()"); final Drawable profileIcon; final Spanned title; Loading @@ -566,7 +513,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements profileIcon = getIcon(this, PROFILE_ICONS.get(deviceProfile)); if (deviceProfile == null) { title = getHtmlFromResources(this, R.string.chooser_title_non_profile, appLabel); title = getHtmlFromResources(this, R.string.chooser_title_non_profile, mAppLabel); mButtonNotAllowMultipleDevices.setText(R.string.consent_no); } else { title = getHtmlFromResources(this, Loading Loading @@ -606,7 +553,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements final DeviceFilterPair<?> selectedDevice = mDeviceAdapter.getItem(position); // To prevent double tap on the selected device. if (mSelectedDevice != null) { if (DEBUG) Log.w(TAG, "Already selected."); Slog.w(TAG, "Already selected."); return; } // Notify the adapter to highlight the selected item. Loading @@ -614,17 +561,9 @@ public class CompanionDeviceActivity extends FragmentActivity implements mSelectedDevice = requireNonNull(selectedDevice); Log.d(TAG, "onDeviceClicked(): " + mSelectedDevice.toShortString()); Slog.d(TAG, "onDeviceClicked(): " + mSelectedDevice.toShortString()); // No need to show permission consent dialog if it is a isSkipPrompt(true) // AssociationRequest. See AssociationRequestsProcessor#mayAssociateWithoutPrompt. if (mRequest.isSkipPrompt()) { Log.d(TAG, "Skipping the permission consent dialog."); onUserSelectedDevice(mSelectedDevice); return; } updatePermissionUi(); updateSingleDeviceUi(); mSummary.setVisibility(View.VISIBLE); mButtonAllow.setVisibility(View.VISIBLE); Loading @@ -633,7 +572,18 @@ public class CompanionDeviceActivity extends FragmentActivity implements mNotAllowMultipleDevicesLayout.setVisibility(View.GONE); } private void updatePermissionUi() { private void updateSingleDeviceUi() { // No need to show permission consent dialog if it is a isSkipPrompt(true) // AssociationRequest. See AssociationRequestsProcessor#mayAssociateWithoutPrompt. if (mRequest.isSkipPrompt()) { Slog.d(TAG, "Skipping the permission consent dialog."); onUserSelectedDevice(mSelectedDevice); return; } mSingleDeviceSpinner.setVisibility(View.GONE); mAssociationConfirmationDialog.setVisibility(View.VISIBLE); final String deviceProfile = mRequest.getDeviceProfile(); final int summaryResourceId = PROFILE_SUMMARIES.get(deviceProfile); final String remoteDeviceName = mSelectedDevice.getDisplayName(); Loading @@ -658,7 +608,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements } private void onPositiveButtonClick(View v) { if (DEBUG) Log.d(TAG, "on_Positive_ButtonClick()"); Slog.d(TAG, "onPositiveButtonClick()"); // Disable the button, to prevent more clicks. v.setEnabled(false); Loading @@ -671,7 +621,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements } private void onNegativeButtonClick(View v) { if (DEBUG) Log.d(TAG, "on_Negative_ButtonClick()"); Slog.d(TAG, "onNegativeButtonClick()"); // Disable the button, to prevent more clicks. v.setEnabled(false); Loading
packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java +10 −40 Original line number Diff line number Diff line Loading @@ -55,7 +55,7 @@ import android.os.IBinder; import android.os.Parcelable; import android.os.SystemProperties; import android.text.TextUtils; import android.util.Log; import android.util.Slog; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; Loading @@ -71,7 +71,6 @@ import java.util.Objects; */ @SuppressLint("LongLogTag") public class CompanionDeviceDiscoveryService extends Service { private static final boolean DEBUG = false; private static final String TAG = "CDM_CompanionDeviceDiscoveryService"; private static final String SYS_PROP_DEBUG_TIMEOUT = "debug.cdm.discovery_timeout"; Loading Loading @@ -147,7 +146,6 @@ public class CompanionDeviceDiscoveryService extends Service { @Override public void onCreate() { super.onCreate(); if (DEBUG) Log.d(TAG, "onCreate()"); mBtManager = getSystemService(BluetoothManager.class); mBtAdapter = mBtManager.getAdapter(); Loading @@ -158,7 +156,6 @@ public class CompanionDeviceDiscoveryService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { final String action = intent.getAction(); if (DEBUG) Log.d(TAG, "onStartCommand() action=" + action); switch (action) { case ACTION_START_DISCOVERY: Loading @@ -174,15 +171,9 @@ public class CompanionDeviceDiscoveryService extends Service { return START_NOT_STICKY; } @Override public void onDestroy() { super.onDestroy(); if (DEBUG) Log.d(TAG, "onDestroy()"); } @MainThread private void startDiscovery(@NonNull AssociationRequest request) { if (DEBUG) Log.i(TAG, "startDiscovery() request=" + request); Slog.d(TAG, "startDiscovery() request=" + request); requireNonNull(request); if (mDiscoveryStarted) throw new RuntimeException("Discovery in progress."); Loading Loading @@ -218,7 +209,7 @@ public class CompanionDeviceDiscoveryService extends Service { @MainThread private void stopDiscoveryAndFinish(boolean timeout) { if (DEBUG) Log.i(TAG, "stopDiscovery()"); Slog.d(TAG, "stopDiscoveryAndFinish(" + timeout + ")"); if (!mDiscoveryStarted) { stopSelf(); Loading Loading @@ -298,10 +289,9 @@ public class CompanionDeviceDiscoveryService extends Service { private BluetoothBroadcastReceiver startBtScanningIfNeeded( List<BluetoothDeviceFilter> filters, boolean force) { if (isEmpty(filters) && !force) return null; if (DEBUG) Log.d(TAG, "registerReceiver(BluetoothDevice.ACTION_FOUND)"); Slog.d(TAG, "registerReceiver(BluetoothDevice.ACTION_FOUND)"); final BluetoothBroadcastReceiver receiver = new BluetoothBroadcastReceiver(filters); final IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(receiver, intentFilter); Loading @@ -313,7 +303,7 @@ public class CompanionDeviceDiscoveryService extends Service { private WifiBroadcastReceiver startWifiScanningIfNeeded( List<WifiDeviceFilter> filters, boolean force) { if (isEmpty(filters) && !force) return null; if (DEBUG) Log.d(TAG, "registerReceiver(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)"); Slog.d(TAG, "registerReceiver(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)"); final WifiBroadcastReceiver receiver = new WifiBroadcastReceiver(filters); Loading @@ -329,10 +319,10 @@ public class CompanionDeviceDiscoveryService extends Service { private ScanCallback startBleScanningIfNeeded( List<BluetoothLeDeviceFilter> filters, boolean force) { if (isEmpty(filters) && !force) return null; if (DEBUG) Log.d(TAG, "BLEScanner.startScan"); Slog.d(TAG, "BLEScanner.startScan"); if (mBleScanner == null) { Log.w(TAG, "BLE Scanner is not available."); Slog.w(TAG, "BLE Scanner is not available."); return null; } Loading @@ -350,18 +340,13 @@ public class CompanionDeviceDiscoveryService extends Service { private void onDeviceFound(@NonNull DeviceFilterPair<?> device) { runOnMainThread(() -> { if (DEBUG) Log.v(TAG, "onDeviceFound() " + device); if (mDiscoveryStopped) return; if (mDevicesFound.contains(device)) { // TODO: update the device instead of ignoring (new found device may contain // additional/updated info, eg. name of the device). if (DEBUG) { Log.d(TAG, "onDeviceFound() " + device.toShortString() + " - Already seen: ignore."); } return; } Log.i(TAG, "onDeviceFound() " + device.toShortString() + " - New device."); Slog.i(TAG, "onDeviceFound() " + device.toShortString() + " - New device."); // First: make change. mDevicesFound.add(device); Loading @@ -376,7 +361,7 @@ public class CompanionDeviceDiscoveryService extends Service { private void onDeviceLost(@NonNull DeviceFilterPair<?> device) { runOnMainThread(() -> { Log.i(TAG, "onDeviceLost(), device=" + device.toShortString()); Slog.i(TAG, "onDeviceLost(), device=" + device.toShortString()); // First: make change. mDevicesFound.remove(device); Loading @@ -395,13 +380,10 @@ public class CompanionDeviceDiscoveryService extends Service { timeout = max(timeout, TIMEOUT_MIN); // should be >= 1 sec (TIMEOUT_MIN) } if (DEBUG) Log.d(TAG, "scheduleTimeout(), timeout=" + timeout); Handler.getMain().postDelayed(mTimeoutRunnable, timeout); } private void timeout() { if (DEBUG) Log.i(TAG, "timeout()"); stopDiscoveryAndFinish(/* timeout */ true); } Loading @@ -419,10 +401,6 @@ public class CompanionDeviceDiscoveryService extends Service { @Override public void onScanResult(int callbackType, ScanResult result) { if (DEBUG) { Log.v(TAG, "BLE.onScanResult() callback=" + callbackType + ", result=" + result); } final DeviceFilterPair<ScanResult> match = findMatch(result, mFilters); if (match == null) return; Loading @@ -447,8 +425,6 @@ public class CompanionDeviceDiscoveryService extends Service { final String action = intent.getAction(); final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (DEBUG) Log.v(TAG, action + ", device=" + device); if (action == null) return; final DeviceFilterPair<BluetoothDevice> match = findMatch(device, mFilters); Loading Loading @@ -477,10 +453,6 @@ public class CompanionDeviceDiscoveryService extends Service { } final List<android.net.wifi.ScanResult> scanResults = mWifiManager.getScanResults(); if (DEBUG) { Log.v(TAG, "WifiManager.SCAN_RESULTS_AVAILABLE_ACTION, results:\n " + TextUtils.join("\n ", scanResults)); } for (int i = 0; i < scanResults.size(); i++) { final android.net.wifi.ScanResult scanResult = scanResults.get(i); Loading @@ -505,9 +477,7 @@ public class CompanionDeviceDiscoveryService extends Service { DeviceFilterPair<T> result = matchingFilter != null ? new DeviceFilterPair<>(dev, matchingFilter) : null; if (DEBUG) { Log.v(TAG, "findMatch(dev=" + dev + ", filters=" + filters + ") -> " + result); } return result; } }
services/companion/java/com/android/server/companion/association/AssociationRequestsProcessor.java +5 −5 Original line number Diff line number Diff line Loading @@ -130,7 +130,7 @@ public class AssociationRequestsProcessor { private final @NonNull PackageManagerInternal mPackageManagerInternal; private final @NonNull AssociationStore mAssociationStore; @NonNull private final ComponentName mCompanionDeviceActivity; private final ComponentName mCompanionAssociationActivity; public AssociationRequestsProcessor(@NonNull Context context, @NonNull PackageManagerInternal packageManagerInternal, Loading @@ -138,9 +138,9 @@ public class AssociationRequestsProcessor { mContext = context; mPackageManagerInternal = packageManagerInternal; mAssociationStore = associationStore; mCompanionDeviceActivity = createRelative( mCompanionAssociationActivity = createRelative( mContext.getString(R.string.config_companionDeviceManagerPackage), ".CompanionDeviceActivity"); ".CompanionAssociationActivity"); } /** Loading Loading @@ -204,7 +204,7 @@ public class AssociationRequestsProcessor { extras.putParcelable(EXTRA_RESULT_RECEIVER, prepareForIpc(mOnRequestConfirmationReceiver)); final Intent intent = new Intent(); intent.setComponent(mCompanionDeviceActivity); intent.setComponent(mCompanionAssociationActivity); intent.putExtras(extras); // 2b.3. Create a PendingIntent. Loading Loading @@ -232,7 +232,7 @@ public class AssociationRequestsProcessor { extras.putBoolean(EXTRA_FORCE_CANCEL_CONFIRMATION, true); final Intent intent = new Intent(); intent.setComponent(mCompanionDeviceActivity); intent.setComponent(mCompanionAssociationActivity); intent.putExtras(extras); return createPendingIntent(packageUid, intent); Loading