• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.nfc;
18 
19 import android.util.Log;
20 
21 import java.util.Arrays;
22 
23 public class NfcProprietaryCaps {
24     private static final String TAG = "NfcProprietaryCaps";
25     private static final int PASSIVE_OBSERVE_MODE = 0;
26     private static final int POLLING_FRAME_NTF = 1;
27     private static final int POWER_SAVING_MODE = 2;
28     private static final int AUTOTRANSACT_POLLING_LOOP_FILTER = 3;
29     private static final int NUMBER_OF_EXIT_FRAMES_SUPPORTED = 4;
30     private static final int READER_MODE_ANNOTATIONS_SUPPORTED = 5;
31     private final PassiveObserveMode mPassiveObserveMode;
32     private final boolean mIsPollingFrameNotificationSupported;
33     private final boolean mIsPowerSavingModeSupported;
34     private final boolean mIsAutotransactPollingLoopFilterSupported;
35     private final int mNumberOfExitFramesSupported;
36     private final boolean mIsReaderModeAnnotationSupported;
37 
38     public enum PassiveObserveMode {
39         NOT_SUPPORTED,
40         SUPPORT_WITH_RF_DEACTIVATION,
41         SUPPORT_WITHOUT_RF_DEACTIVATION,
42     }
43 
getPassiveObserveMode()44     public PassiveObserveMode getPassiveObserveMode() {
45         return mPassiveObserveMode;
46     }
47 
isPollingFrameNotificationSupported()48     public boolean isPollingFrameNotificationSupported() {
49         return mIsPollingFrameNotificationSupported;
50     }
51 
isPowerSavingModeSupported()52     public boolean isPowerSavingModeSupported() {
53         return mIsPowerSavingModeSupported;
54     }
55 
isAutotransactPollingLoopFilterSupported()56     public boolean isAutotransactPollingLoopFilterSupported() {
57         return mIsAutotransactPollingLoopFilterSupported;
58     }
59 
getNumberOfExitFramesSupported()60     public int getNumberOfExitFramesSupported() {
61         return mNumberOfExitFramesSupported;
62     }
63 
isReaderModeAnnotationSupported()64     public boolean isReaderModeAnnotationSupported() {
65         return mIsReaderModeAnnotationSupported;
66     }
67 
NfcProprietaryCaps(PassiveObserveMode passiveObserveMode, boolean isPollingFrameNotificationSupported, boolean isPowerSavingModeSupported, boolean isAutotransactPollingLoopFilterSupported, int numberOfExitFramesSupported, boolean isReaderModeAnnotationSupported)68     public NfcProprietaryCaps(PassiveObserveMode passiveObserveMode,
69             boolean isPollingFrameNotificationSupported, boolean isPowerSavingModeSupported,
70             boolean isAutotransactPollingLoopFilterSupported, int numberOfExitFramesSupported,
71             boolean isReaderModeAnnotationSupported) {
72         mPassiveObserveMode = passiveObserveMode;
73         mIsPollingFrameNotificationSupported = isPollingFrameNotificationSupported;
74         mIsPowerSavingModeSupported = isPowerSavingModeSupported;
75         mIsAutotransactPollingLoopFilterSupported = isAutotransactPollingLoopFilterSupported;
76         mNumberOfExitFramesSupported = numberOfExitFramesSupported;
77         mIsReaderModeAnnotationSupported = isReaderModeAnnotationSupported;
78     }
79 
createFromByteArray(byte[] caps)80     public static NfcProprietaryCaps createFromByteArray(byte[] caps) {
81         Log.i(TAG, "createFromByteArray: parsing proprietary caps: " + Arrays.toString(caps));
82         PassiveObserveMode passiveObserveMode = PassiveObserveMode.NOT_SUPPORTED;
83         boolean isPollingFrameNotificationSupported = false;
84         boolean isPowerSavingModeSupported = false;
85         boolean isAutotransactPollingLoopFilterSupported  = false;
86         int numberOfExitFramesSupported = 0;
87         boolean isReaderModeAnnotationSupported = false;
88         int offset = 0;
89         while ((offset + 2) < caps.length) {
90             int id = caps[offset++];
91             int value_len = caps[offset++];
92             int value_offset = offset;
93             offset += value_len;
94 
95             // value bounds check
96             // all caps have minimum length of 1, check this bound
97             // here to simplify match cases.
98             if (value_len < 1 || offset > caps.length) {
99                 break;
100             }
101             switch (id) {
102                 case PASSIVE_OBSERVE_MODE:
103                     passiveObserveMode = switch (caps[value_offset]) {
104                         case 0 -> PassiveObserveMode.NOT_SUPPORTED;
105                         case 1 -> PassiveObserveMode.SUPPORT_WITH_RF_DEACTIVATION;
106                         case 2 -> PassiveObserveMode.SUPPORT_WITHOUT_RF_DEACTIVATION;
107                         default -> passiveObserveMode;
108                     };
109                     break;
110                 case POLLING_FRAME_NTF:
111                     isPollingFrameNotificationSupported = caps[value_offset] == 0x1;
112                     break;
113                 case POWER_SAVING_MODE:
114                     isPowerSavingModeSupported = caps[value_offset] == 0x1;
115                     break;
116                 case AUTOTRANSACT_POLLING_LOOP_FILTER:
117                     isAutotransactPollingLoopFilterSupported = caps[value_offset] == 0x1;
118                     break;
119                 case NUMBER_OF_EXIT_FRAMES_SUPPORTED:
120                     numberOfExitFramesSupported = caps[value_offset];
121                 case READER_MODE_ANNOTATIONS_SUPPORTED:
122                     isReaderModeAnnotationSupported = caps[value_offset] == 0x1;
123                     break;
124 
125             }
126         }
127         return new NfcProprietaryCaps(passiveObserveMode, isPollingFrameNotificationSupported,
128                 isPowerSavingModeSupported, isAutotransactPollingLoopFilterSupported,
129                 numberOfExitFramesSupported, isReaderModeAnnotationSupported);
130     }
131 
132     @Override
toString()133     public String toString() {
134         return "NfcProprietaryCaps{"
135                 + "passiveObserveMode="
136                 + mPassiveObserveMode
137                 + ", isPollingFrameNotificationSupported="
138                 + mIsPollingFrameNotificationSupported
139                 + ", isPowerSavingModeSupported="
140                 + mIsPowerSavingModeSupported
141                 + ", isAutotransactPollingLoopFilterSupported="
142                 + mIsAutotransactPollingLoopFilterSupported
143                 + ", mIsReaderModeAnnotationSupported="
144                 + mIsReaderModeAnnotationSupported
145                 + '}';
146     }
147 }
148