• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.android.nearby.halfsheet.utils;
17 
18 import static com.android.nearby.halfsheet.constants.UserActionHandlerBase.ACTION_FAST_PAIR;
19 import static com.android.nearby.halfsheet.constants.UserActionHandlerBase.EXTRA_COMPANION_APP;
20 
21 import android.bluetooth.BluetoothAdapter;
22 import android.bluetooth.BluetoothDevice;
23 import android.bluetooth.BluetoothManager;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.pm.PackageManager;
27 import android.util.Log;
28 
29 import androidx.annotation.NonNull;
30 import androidx.annotation.Nullable;
31 
32 import java.net.URISyntaxException;
33 
34 import service.proto.Cache;
35 
36 /**
37  * Util class in half sheet apk
38  */
39 public class FastPairUtils {
40 
41     /** FastPair util method check certain app is install on the device or not. */
isAppInstalled(Context context, String packageName)42     public static boolean isAppInstalled(Context context, String packageName) {
43         try {
44             context.getPackageManager().getPackageInfo(packageName, 0);
45             return true;
46         } catch (PackageManager.NameNotFoundException e) {
47             return false;
48         }
49     }
50 
51     /** FastPair util method to properly format the action url extra. */
52     @Nullable
getCompanionAppFromActionUrl(String actionUrl)53     public static String getCompanionAppFromActionUrl(String actionUrl) {
54         try {
55             Intent intent = Intent.parseUri(actionUrl, Intent.URI_INTENT_SCHEME);
56             if (!intent.getAction().equals(ACTION_FAST_PAIR)) {
57                 Log.e("FastPairUtils", "Companion app launch attempted from malformed action url");
58                 return null;
59             }
60             return intent.getStringExtra(EXTRA_COMPANION_APP);
61         } catch (URISyntaxException e) {
62             Log.e("FastPairUtils", "FastPair: fail to get companion app info from discovery item");
63             return null;
64         }
65     }
66 
67     /**
68      * Converts {@link service.proto.Cache.StoredDiscoveryItem} from
69      * {@link service.proto.Cache.ScanFastPairStoreItem}
70      */
convertFrom(Cache.ScanFastPairStoreItem item)71     public static Cache.StoredDiscoveryItem convertFrom(Cache.ScanFastPairStoreItem item) {
72         return convertFrom(item, /* isSubsequentPair= */ false);
73     }
74 
75     /**
76      * Converts a {@link service.proto.Cache.ScanFastPairStoreItem}
77      * to a {@link service.proto.Cache.StoredDiscoveryItem}.
78      *
79      * <p>This is needed to make the new Fast Pair scanning stack compatible with the rest of the
80      * legacy Fast Pair code.
81      */
convertFrom( Cache.ScanFastPairStoreItem item, boolean isSubsequentPair)82     public static Cache.StoredDiscoveryItem convertFrom(
83             Cache.ScanFastPairStoreItem item, boolean isSubsequentPair) {
84         return Cache.StoredDiscoveryItem.newBuilder()
85                 .setId(item.getModelId())
86                 .setFirstObservationTimestampMillis(item.getFirstObservationTimestampMillis())
87                 .setLastObservationTimestampMillis(item.getLastObservationTimestampMillis())
88                 .setActionUrl(item.getActionUrl())
89                 .setActionUrlType(Cache.ResolvedUrlType.APP)
90                 .setTitle(
91                         isSubsequentPair
92                                 ? item.getFastPairStrings().getTapToPairWithoutAccount()
93                                 : item.getDeviceName())
94                 .setMacAddress(item.getAddress())
95                 .setState(Cache.StoredDiscoveryItem.State.STATE_ENABLED)
96                 .setTriggerId(item.getModelId())
97                 .setIconPng(item.getIconPng())
98                 .setIconFifeUrl(item.getIconFifeUrl())
99                 .setDescription(
100                         isSubsequentPair
101                                 ? item.getDeviceName()
102                                 : item.getFastPairStrings().getTapToPairWithoutAccount())
103                 .setAuthenticationPublicKeySecp256R1(item.getAntiSpoofingPublicKey())
104                 .setCompanionDetail(item.getCompanionDetail())
105                 .setFastPairStrings(item.getFastPairStrings())
106                 .setFastPairInformation(
107                         Cache.FastPairInformation.newBuilder()
108                                 .setDataOnlyConnection(item.getDataOnlyConnection())
109                                 .setTrueWirelessImages(item.getTrueWirelessImages())
110                                 .setAssistantSupported(item.getAssistantSupported())
111                                 .setCompanyName(item.getCompanyName()))
112                 .build();
113     }
114 
115     /**
116      * Returns true the application is installed and can be opened on device.
117      */
isLaunchable(@onNull Context context, String companionApp)118     public static boolean isLaunchable(@NonNull Context context, String companionApp) {
119         return isAppInstalled(context, companionApp)
120                 && createCompanionAppIntent(context, companionApp, null) != null;
121     }
122 
123     /**
124      * Returns an intent to launch given the package name and bluetooth address (if provided).
125      * Returns null if no such an intent can be found.
126      */
127     @Nullable
createCompanionAppIntent(@onNull Context context, String packageName, @Nullable String address)128     public static Intent createCompanionAppIntent(@NonNull Context context, String packageName,
129             @Nullable String address) {
130         Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
131         if (intent == null) {
132             return null;
133         }
134         if (address != null) {
135             BluetoothAdapter adapter = getBluetoothAdapter(context);
136             if (adapter != null) {
137                 intent.putExtra(BluetoothDevice.EXTRA_DEVICE, adapter.getRemoteDevice(address));
138             }
139         }
140         return intent;
141     }
142 
143     @Nullable
getBluetoothAdapter(@onNull Context context)144     private static BluetoothAdapter getBluetoothAdapter(@NonNull Context context) {
145         BluetoothManager bluetoothManager = context.getSystemService(BluetoothManager.class);
146         return bluetoothManager == null ? null : bluetoothManager.getAdapter();
147     }
148 
FastPairUtils()149     private FastPairUtils() {}
150 }
151