diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java index 21d700e41a40b..f4558feb69aab 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java @@ -16,180 +16,46 @@ package com.android.systemui.usb; -import android.app.AlertDialog; -import android.content.ComponentName; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.PermissionChecker; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.hardware.usb.IUsbManager; -import android.hardware.usb.UsbAccessory; -import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbManager; -import android.os.Bundle; -import android.os.IBinder; -import android.os.ServiceManager; -import android.os.UserHandle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.Window; -import android.view.WindowManager; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.TextView; - -import com.android.internal.app.AlertActivity; -import com.android.internal.app.AlertController; import com.android.systemui.R; -public class UsbConfirmActivity extends AlertActivity - implements DialogInterface.OnClickListener, CheckBox.OnCheckedChangeListener { - - private static final String TAG = "UsbConfirmActivity"; - - private CheckBox mAlwaysUse; - private TextView mClearDefaultHint; - private UsbDevice mDevice; - private UsbAccessory mAccessory; - private ResolveInfo mResolveInfo; - private boolean mPermissionGranted; - private UsbDisconnectedReceiver mDisconnectedReceiver; +/** + * Dialog shown to confirm the package to start when a USB device or accessory is attached and there + * is only one package that claims to handle this USB device or accessory. + */ +public class UsbConfirmActivity extends UsbDialogActivity { @Override - public void onCreate(Bundle icicle) { - getWindow().addSystemFlags( - WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); - - super.onCreate(icicle); - - Intent intent = getIntent(); - mDevice = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); - mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); - mResolveInfo = (ResolveInfo) intent.getParcelableExtra("rinfo"); - String packageName = intent.getStringExtra(UsbManager.EXTRA_PACKAGE); - - PackageManager packageManager = getPackageManager(); - String appName = mResolveInfo.loadLabel(packageManager).toString(); - - final AlertController.AlertParams ap = mAlertParams; - ap.mTitle = appName; + protected void onResume() { + super.onResume(); + final int strId; boolean useRecordWarning = false; - if (mDevice == null) { - ap.mMessage = getString(R.string.usb_accessory_confirm_prompt, appName, - mAccessory.getDescription()); - mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory); - } else { - int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); - boolean hasRecordPermission = - PermissionChecker.checkPermissionForPreflight( - this, android.Manifest.permission.RECORD_AUDIO, -1, uid, - packageName) - == android.content.pm.PackageManager.PERMISSION_GRANTED; - boolean isAudioCaptureDevice = mDevice.getHasAudioCapture(); - useRecordWarning = isAudioCaptureDevice && !hasRecordPermission; - - int strID = useRecordWarning + if (mDialogHelper.isUsbDevice()) { + useRecordWarning = mDialogHelper.deviceHasAudioCapture() + && !mDialogHelper.packageHasAudioRecordingPermission(); + strId = useRecordWarning ? R.string.usb_device_confirm_prompt_warn : R.string.usb_device_confirm_prompt; - - ap.mMessage = getString(strID, appName, mDevice.getProductName()); - mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice); + } else { + // UsbAccessory case + strId = R.string.usb_accessory_confirm_prompt; } - ap.mPositiveButtonText = getString(android.R.string.ok); - ap.mNegativeButtonText = getString(android.R.string.cancel); - ap.mPositiveButtonListener = this; - ap.mNegativeButtonListener = this; - - // add "always use" checkbox + setAlertParams(strId); + // Only show the "always use" checkbox if there is no USB/Record warning if (!useRecordWarning) { - LayoutInflater inflater = (LayoutInflater) getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null); - mAlwaysUse = (CheckBox) ap.mView.findViewById(com.android.internal.R.id.alwaysUse); - if (mDevice == null) { - mAlwaysUse.setText(getString(R.string.always_use_accessory, appName, - mAccessory.getDescription())); - } else { - mAlwaysUse.setText(getString(R.string.always_use_device, appName, - mDevice.getProductName())); - } - mAlwaysUse.setOnCheckedChangeListener(this); - mClearDefaultHint = (TextView) ap.mView.findViewById( - com.android.internal.R.id.clearDefaultHint); - mClearDefaultHint.setVisibility(View.GONE); + addAlwaysUseCheckbox(); } setupAlert(); - } @Override - protected void onDestroy() { - if (mDisconnectedReceiver != null) { - unregisterReceiver(mDisconnectedReceiver); - } - super.onDestroy(); - } - - public void onClick(DialogInterface dialog, int which) { - if (which == AlertDialog.BUTTON_POSITIVE) { - try { - IBinder b = ServiceManager.getService(USB_SERVICE); - IUsbManager service = IUsbManager.Stub.asInterface(b); - final int uid = mResolveInfo.activityInfo.applicationInfo.uid; - final int userId = UserHandle.myUserId(); - boolean alwaysUse = mAlwaysUse != null ? mAlwaysUse.isChecked() : false; - Intent intent = null; - - if (mDevice != null) { - intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED); - intent.putExtra(UsbManager.EXTRA_DEVICE, mDevice); - - // grant permission for the device - service.grantDevicePermission(mDevice, uid); - // set or clear default setting - if (alwaysUse) { - service.setDevicePackage( - mDevice, mResolveInfo.activityInfo.packageName, userId); - } else { - service.setDevicePackage(mDevice, null, userId); - } - } else if (mAccessory != null) { - intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_ATTACHED); - intent.putExtra(UsbManager.EXTRA_ACCESSORY, mAccessory); - - // grant permission for the accessory - service.grantAccessoryPermission(mAccessory, uid); - // set or clear default setting - if (alwaysUse) { - service.setAccessoryPackage( - mAccessory, mResolveInfo.activityInfo.packageName, userId); - } else { - service.setAccessoryPackage(mAccessory, null, userId); - } - } - - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.setComponent( - new ComponentName(mResolveInfo.activityInfo.packageName, - mResolveInfo.activityInfo.name)); - startActivityAsUser(intent, new UserHandle(userId)); - } catch (Exception e) { - Log.e(TAG, "Unable to start activity", e); - } + void onConfirm() { + mDialogHelper.grantUidAccessPermission(); + if (isAlwaysUseChecked()) { + mDialogHelper.setDefaultPackage(); + } else { + mDialogHelper.clearDefaultPackage(); } + mDialogHelper.confirmDialogStartActivity(); finish(); } - - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - if (mClearDefaultHint == null) return; - - if(isChecked) { - mClearDefaultHint.setVisibility(View.VISIBLE); - } else { - mClearDefaultHint.setVisibility(View.GONE); - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDialogActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDialogActivity.java new file mode 100644 index 0000000000000..930bc338a9180 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDialogActivity.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.usb; + +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.WindowManager; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.TextView; + +import com.android.internal.app.AlertActivity; +import com.android.internal.app.AlertController; +import com.android.systemui.R; + +abstract class UsbDialogActivity extends AlertActivity + implements DialogInterface.OnClickListener, CheckBox.OnCheckedChangeListener { + + private static final String TAG = UsbDialogActivity.class.getSimpleName(); + + UsbDialogHelper mDialogHelper; + private CheckBox mAlwaysUse; + private TextView mClearDefaultHint; + + @Override + protected final void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().addSystemFlags( + WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); + try { + mDialogHelper = new UsbDialogHelper(getApplicationContext(), getIntent()); + } catch (IllegalStateException e) { + Log.e(TAG, "unable to initialize", e); + finish(); + } + } + + @Override + protected void onResume() { + super.onResume(); + mDialogHelper.registerUsbDisconnectedReceiver(this); + } + + @Override + protected void onPause() { + if (mDialogHelper != null) { + mDialogHelper.unregisterUsbDisconnectedReceiver(this); + } + super.onPause(); + } + + @Override + public void onClick(DialogInterface dialog, int which) { + if (which == AlertDialog.BUTTON_POSITIVE) { + onConfirm(); + } else { + finish(); + } + } + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (mClearDefaultHint == null) return; + + if (isChecked) { + mClearDefaultHint.setVisibility(View.VISIBLE); + } else { + mClearDefaultHint.setVisibility(View.GONE); + } + } + + void setAlertParams(int strId) { + final AlertController.AlertParams ap = mAlertParams; + ap.mTitle = mDialogHelper.getAppName(); + ap.mMessage = getString(strId, mDialogHelper.getAppName(), + mDialogHelper.getDeviceDescription()); + ap.mPositiveButtonText = getString(android.R.string.ok); + ap.mNegativeButtonText = getString(android.R.string.cancel); + ap.mPositiveButtonListener = this; + ap.mNegativeButtonListener = this; + } + + void addAlwaysUseCheckbox() { + final AlertController.AlertParams ap = mAlertParams; + LayoutInflater inflater = getSystemService(LayoutInflater.class); + ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null); + mAlwaysUse = ap.mView.findViewById(com.android.internal.R.id.alwaysUse); + if (mDialogHelper.isUsbAccessory()) { + mAlwaysUse.setText(getString(R.string.always_use_accessory, mDialogHelper.getAppName(), + mDialogHelper.getDeviceDescription())); + } else { + // UsbDevice case + mAlwaysUse.setText(getString(R.string.always_use_device, mDialogHelper.getAppName(), + mDialogHelper.getDeviceDescription())); + } + mAlwaysUse.setOnCheckedChangeListener(this); + mClearDefaultHint = ap.mView.findViewById(com.android.internal.R.id.clearDefaultHint); + mClearDefaultHint.setVisibility(View.GONE); + } + + boolean isAlwaysUseChecked() { + return mAlwaysUse != null && mAlwaysUse.isChecked(); + } + + /** + * Called when the dialog is confirmed. + */ + abstract void onConfirm(); +} diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java index bfa50bcee2703..38d634777177c 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java @@ -16,186 +16,53 @@ package com.android.systemui.usb; -import android.app.AlertDialog; -import android.app.PendingIntent; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.PermissionChecker; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.hardware.usb.IUsbManager; -import android.hardware.usb.UsbAccessory; -import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbManager; -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.UserHandle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.WindowManager; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.TextView; - -import com.android.internal.app.AlertActivity; -import com.android.internal.app.AlertController; import com.android.systemui.R; -public class UsbPermissionActivity extends AlertActivity - implements DialogInterface.OnClickListener, CheckBox.OnCheckedChangeListener { +/** + * Dialog shown when a package requests access to a USB device or accessory. + */ +public class UsbPermissionActivity extends UsbDialogActivity { - private static final String TAG = "UsbPermissionActivity"; - - private CheckBox mAlwaysUse; - private TextView mClearDefaultHint; - private UsbDevice mDevice; - private UsbAccessory mAccessory; - private PendingIntent mPendingIntent; - private String mPackageName; - private int mUid; - private boolean mPermissionGranted; - private UsbDisconnectedReceiver mDisconnectedReceiver; + private boolean mPermissionGranted = false; @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - - getWindow().addPrivateFlags( - WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); - Intent intent = getIntent(); - mDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); - mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); - mPendingIntent = (PendingIntent)intent.getParcelableExtra(Intent.EXTRA_INTENT); - mUid = intent.getIntExtra(Intent.EXTRA_UID, -1); - mPackageName = intent.getStringExtra(UsbManager.EXTRA_PACKAGE); - boolean canBeDefault = intent.getBooleanExtra(UsbManager.EXTRA_CAN_BE_DEFAULT, false); - - PackageManager packageManager = getPackageManager(); - ApplicationInfo aInfo; - try { - aInfo = packageManager.getApplicationInfo(mPackageName, 0); - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "unable to look up package name", e); - finish(); - return; - } - String appName = aInfo.loadLabel(packageManager).toString(); - - final AlertController.AlertParams ap = mAlertParams; - ap.mTitle = appName; + protected void onResume() { + super.onResume(); + final int strId; boolean useRecordWarning = false; - if (mDevice == null) { - // Accessory Case - - ap.mMessage = getString(R.string.usb_accessory_permission_prompt, appName, - mAccessory.getDescription()); - mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory); - } else { - boolean hasRecordPermission = - PermissionChecker.checkPermissionForPreflight( - this, android.Manifest.permission.RECORD_AUDIO, -1, aInfo.uid, - mPackageName) - == android.content.pm.PackageManager.PERMISSION_GRANTED; - boolean isAudioCaptureDevice = mDevice.getHasAudioCapture(); - useRecordWarning = isAudioCaptureDevice && !hasRecordPermission; - - int strID = useRecordWarning + if (mDialogHelper.isUsbDevice()) { + useRecordWarning = mDialogHelper.deviceHasAudioCapture() + && !mDialogHelper.packageHasAudioRecordingPermission(); + strId = useRecordWarning ? R.string.usb_device_permission_prompt_warn : R.string.usb_device_permission_prompt; - ap.mMessage = getString(strID, appName, mDevice.getProductName()); - mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice); - + } else { + // UsbAccessory case + strId = R.string.usb_accessory_permission_prompt; } - - ap.mPositiveButtonText = getString(android.R.string.ok); - ap.mNegativeButtonText = getString(android.R.string.cancel); - ap.mPositiveButtonListener = this; - ap.mNegativeButtonListener = this; - - // Don't show the "always use" checkbox if the USB/Record warning is in effect - if (!useRecordWarning && canBeDefault && (mDevice != null || mAccessory != null)) { - // add "open when" checkbox - LayoutInflater inflater = (LayoutInflater) getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null); - mAlwaysUse = (CheckBox) ap.mView.findViewById(com.android.internal.R.id.alwaysUse); - if (mDevice == null) { - mAlwaysUse.setText(getString(R.string.always_use_accessory, appName, - mAccessory.getDescription())); - } else { - mAlwaysUse.setText(getString(R.string.always_use_device, appName, - mDevice.getProductName())); - } - mAlwaysUse.setOnCheckedChangeListener(this); - - mClearDefaultHint = (TextView)ap.mView.findViewById( - com.android.internal.R.id.clearDefaultHint); - mClearDefaultHint.setVisibility(View.GONE); + setAlertParams(strId); + // Only show the "always use" checkbox if there is no USB/Record warning + if (!useRecordWarning && mDialogHelper.canBeDefault()) { + addAlwaysUseCheckbox(); } - setupAlert(); } @Override - public void onDestroy() { - IBinder b = ServiceManager.getService(USB_SERVICE); - IUsbManager service = IUsbManager.Stub.asInterface(b); - - // send response via pending intent - Intent intent = new Intent(); - try { - if (mDevice != null) { - intent.putExtra(UsbManager.EXTRA_DEVICE, mDevice); - if (mPermissionGranted) { - service.grantDevicePermission(mDevice, mUid); - if (mAlwaysUse != null && mAlwaysUse.isChecked()) { - final int userId = UserHandle.getUserId(mUid); - service.setDevicePackage(mDevice, mPackageName, userId); - } - } - } - if (mAccessory != null) { - intent.putExtra(UsbManager.EXTRA_ACCESSORY, mAccessory); - if (mPermissionGranted) { - service.grantAccessoryPermission(mAccessory, mUid); - if (mAlwaysUse != null && mAlwaysUse.isChecked()) { - final int userId = UserHandle.getUserId(mUid); - service.setAccessoryPackage(mAccessory, mPackageName, userId); - } - } - } - intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, mPermissionGranted); - mPendingIntent.send(this, 0, intent); - } catch (PendingIntent.CanceledException e) { - Log.w(TAG, "PendingIntent was cancelled"); - } catch (RemoteException e) { - Log.e(TAG, "IUsbService connection failed", e); + protected void onPause() { + if (isFinishing()) { + mDialogHelper.sendPermissionDialogResponse(mPermissionGranted); } - - if (mDisconnectedReceiver != null) { - unregisterReceiver(mDisconnectedReceiver); - } - super.onDestroy(); + super.onPause(); } - public void onClick(DialogInterface dialog, int which) { - if (which == AlertDialog.BUTTON_POSITIVE) { - mPermissionGranted = true; + @Override + void onConfirm() { + mDialogHelper.grantUidAccessPermission(); + if (isAlwaysUseChecked()) { + mDialogHelper.setDefaultPackage(); } + mPermissionGranted = true; finish(); } - - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - if (mClearDefaultHint == null) return; - - if(isChecked) { - mClearDefaultHint.setVisibility(View.VISIBLE); - } else { - mClearDefaultHint.setVisibility(View.GONE); - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java index 0aa965b2d750d..842dcb8ce52e1 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java @@ -19,6 +19,7 @@ package com.android.systemui.usb; import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE; import android.content.ActivityNotFoundException; +import android.content.ComponentName; import android.content.Intent; import android.content.pm.ResolveInfo; import android.hardware.usb.IUsbManager; @@ -109,7 +110,9 @@ public class UsbResolverActivity extends ResolverActivity { mOtherProfileIntent.putParcelableArrayListExtra(EXTRA_RESOLVE_INFOS, rListOtherProfile); } else { - mOtherProfileIntent = new Intent(this, UsbConfirmActivity.class); + mOtherProfileIntent.setComponent(ComponentName.unflattenFromString( + this.getResources().getString( + com.android.internal.R.string.config_usbConfirmActivity))); mOtherProfileIntent.putExtra(EXTRA_RESOLVE_INFO, rListOtherProfile.get(0)); if (mDevice != null) {