1 /* 2 * Copyright (C) 2021 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.systemui.qs.tiles; 18 19 import android.content.Intent; 20 import android.os.Handler; 21 import android.os.Looper; 22 import android.service.quicksettings.Tile; 23 import android.util.Log; 24 import android.view.View; 25 26 import androidx.annotation.Nullable; 27 28 import com.android.internal.jank.InteractionJankMonitor; 29 import com.android.internal.logging.MetricsLogger; 30 import com.android.systemui.R; 31 import com.android.systemui.animation.ActivityLaunchAnimator; 32 import com.android.systemui.dagger.qualifiers.Background; 33 import com.android.systemui.dagger.qualifiers.Main; 34 import com.android.systemui.plugins.ActivityStarter; 35 import com.android.systemui.plugins.FalsingManager; 36 import com.android.systemui.plugins.qs.QSTile; 37 import com.android.systemui.plugins.statusbar.StatusBarStateController; 38 import com.android.systemui.qrcodescanner.controller.QRCodeScannerController; 39 import com.android.systemui.qs.QSHost; 40 import com.android.systemui.qs.QsEventLogger; 41 import com.android.systemui.qs.logging.QSLogger; 42 import com.android.systemui.qs.tileimpl.QSTileImpl; 43 44 import javax.inject.Inject; 45 46 /** Quick settings tile: QR Code Scanner **/ 47 public class QRCodeScannerTile extends QSTileImpl<QSTile.State> { 48 49 public static final String TILE_SPEC = "qr_code_scanner"; 50 51 private static final String TAG = "QRCodeScanner"; 52 53 private final CharSequence mLabel = mContext.getString(R.string.qr_code_scanner_title); 54 private final QRCodeScannerController mQRCodeScannerController; 55 56 private final QRCodeScannerController.Callback mCallback = 57 new QRCodeScannerController.Callback() { 58 public void onQRCodeScannerActivityChanged() { 59 refreshState(); 60 } 61 }; 62 63 @Inject QRCodeScannerTile( QSHost host, QsEventLogger uiEventLogger, @Background Looper backgroundLooper, @Main Handler mainHandler, FalsingManager falsingManager, MetricsLogger metricsLogger, StatusBarStateController statusBarStateController, ActivityStarter activityStarter, QSLogger qsLogger, QRCodeScannerController qrCodeScannerController)64 public QRCodeScannerTile( 65 QSHost host, 66 QsEventLogger uiEventLogger, 67 @Background Looper backgroundLooper, 68 @Main Handler mainHandler, 69 FalsingManager falsingManager, 70 MetricsLogger metricsLogger, 71 StatusBarStateController statusBarStateController, 72 ActivityStarter activityStarter, 73 QSLogger qsLogger, 74 QRCodeScannerController qrCodeScannerController) { 75 super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, 76 statusBarStateController, activityStarter, qsLogger); 77 mQRCodeScannerController = qrCodeScannerController; 78 mQRCodeScannerController.observe(getLifecycle(), mCallback); 79 } 80 81 @Override handleInitialize()82 protected void handleInitialize() { 83 mQRCodeScannerController.registerQRCodeScannerChangeObservers( 84 QRCodeScannerController.DEFAULT_QR_CODE_SCANNER_CHANGE); 85 } 86 87 @Override handleDestroy()88 protected void handleDestroy() { 89 super.handleDestroy(); 90 mQRCodeScannerController.unregisterQRCodeScannerChangeObservers( 91 QRCodeScannerController.DEFAULT_QR_CODE_SCANNER_CHANGE); 92 } 93 94 @Override newTileState()95 public State newTileState() { 96 State state = new State(); 97 state.handlesLongClick = false; 98 return state; 99 } 100 101 @Override handleClick(@ullable View view)102 protected void handleClick(@Nullable View view) { 103 Intent intent = mQRCodeScannerController.getIntent(); 104 if (intent == null) { 105 // This should never happen as the fact that we are handling clicks means that the 106 // scanner is available. This is just a safety check. 107 Log.e(TAG, "Expected a non-null intent"); 108 return; 109 } 110 111 ActivityLaunchAnimator.Controller animationController = 112 view == null ? null : ActivityLaunchAnimator.Controller.fromView(view, 113 InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE); 114 mActivityStarter.startActivity(intent, true /* dismissShade */, 115 animationController, true /* showOverLockscreenWhenLocked */); 116 } 117 118 @Override handleUpdateState(State state, Object arg)119 protected void handleUpdateState(State state, Object arg) { 120 state.label = mContext.getString(R.string.qr_code_scanner_title); 121 state.contentDescription = state.label; 122 state.icon = ResourceIcon.get(R.drawable.ic_qr_code_scanner); 123 state.state = mQRCodeScannerController.isAbleToLaunchScannerActivity() ? Tile.STATE_INACTIVE 124 : Tile.STATE_UNAVAILABLE; 125 // The assumption is that if the OEM has the QR code scanner module enabled then the scanner 126 // would go to "Unavailable" state only when GMS core is updating. 127 state.secondaryLabel = state.state == Tile.STATE_UNAVAILABLE 128 ? mContext.getString(R.string.qr_code_scanner_updating_secondary_label) : null; 129 } 130 131 @Override getMetricsCategory()132 public int getMetricsCategory() { 133 // New logging doesn't use this, keeping the function for legacy code. 134 return 0; 135 } 136 137 @Override isAvailable()138 public boolean isAvailable() { 139 return mQRCodeScannerController.isCameraAvailable(); 140 } 141 142 @Nullable 143 @Override getLongClickIntent()144 public Intent getLongClickIntent() { 145 return null; 146 } 147 148 @Override getTileLabel()149 public CharSequence getTileLabel() { 150 return mLabel; 151 } 152 } 153