ronnie
2023-02-07 4382dc0b492f08fac9cc178333329b28204dfb09
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/*
 * Copyright (C) 2017 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.server.oemlock;
 
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.oemlock.V1_0.IOemLock;
import android.hardware.oemlock.V1_0.OemLockSecureStatus;
import android.hardware.oemlock.V1_0.OemLockStatus;
import android.os.RemoteException;
import android.util.Slog;
 
import java.util.ArrayList;
import java.util.NoSuchElementException;
 
/**
 * Uses the OEM lock HAL.
 */
class VendorLock extends OemLock {
    private static final String TAG = "OemLock";
 
    private Context mContext;
    private IOemLock mOemLock;
 
    static IOemLock getOemLockHalService() {
        try {
            return IOemLock.getService();
        } catch (NoSuchElementException e) {
            Slog.i(TAG, "OemLock HAL not present on device");
            return null;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
 
    VendorLock(Context context, IOemLock oemLock) {
        mContext = context;
        mOemLock = oemLock;
    }
 
    @Override
    @Nullable
    String getLockName() {
        final Integer[] requestStatus = new Integer[1];
        final String[] lockName = new String[1];
 
        try {
            mOemLock.getName((status, name) -> {
                requestStatus[0] = status;
                lockName[0] = name;
            });
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to get name from HAL", e);
            throw e.rethrowFromSystemServer();
        }
 
        switch (requestStatus[0]) {
            case OemLockStatus.OK:
                // Success
                return lockName[0];
 
            case OemLockStatus.FAILED:
                Slog.e(TAG, "Failed to get OEM lock name.");
                return null;
 
            default:
                Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL");
                return null;
        }
    }
 
    @Override
    void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
        try {
            ArrayList<Byte> signatureBytes = toByteArrayList(signature);
            switch (mOemLock.setOemUnlockAllowedByCarrier(allowed, signatureBytes)) {
                case OemLockSecureStatus.OK:
                    Slog.i(TAG, "Updated carrier allows OEM lock state to: " + allowed);
                    return;
 
                case OemLockSecureStatus.INVALID_SIGNATURE:
                    if (signatureBytes.isEmpty()) {
                        throw new IllegalArgumentException("Signature required for carrier unlock");
                    }
                    throw new SecurityException(
                            "Invalid signature used in attempt to carrier unlock");
 
                default:
                    Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL");
                    // Fallthrough
                case OemLockSecureStatus.FAILED:
                    throw new RuntimeException("Failed to set carrier OEM unlock state");
            }
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to set carrier state with HAL", e);
            throw e.rethrowFromSystemServer();
        }
    }
 
    @Override
    boolean isOemUnlockAllowedByCarrier() {
        final Integer[] requestStatus = new Integer[1];
        final Boolean[] allowedByCarrier = new Boolean[1];
 
        try {
            mOemLock.isOemUnlockAllowedByCarrier((status, allowed) -> {
                requestStatus[0] = status;
                allowedByCarrier[0] = allowed;
            });
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to get carrier state from HAL");
            throw e.rethrowFromSystemServer();
        }
 
        switch (requestStatus[0]) {
            case OemLockStatus.OK:
                // Success
                return allowedByCarrier[0];
 
            default:
                Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL");
                // Fallthrough
            case OemLockStatus.FAILED:
                throw new RuntimeException("Failed to get carrier OEM unlock state");
        }
    }
 
    @Override
    void setOemUnlockAllowedByDevice(boolean allowedByDevice) {
        try {
            switch (mOemLock.setOemUnlockAllowedByDevice(allowedByDevice)) {
                case OemLockSecureStatus.OK:
                    Slog.i(TAG, "Updated device allows OEM lock state to: " + allowedByDevice);
                    return;
 
                default:
                    Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL");
                    // Fallthrough
                case OemLockSecureStatus.FAILED:
                    throw new RuntimeException("Failed to set device OEM unlock state");
            }
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to set device state with HAL", e);
            throw e.rethrowFromSystemServer();
        }
    }
 
    @Override
    boolean isOemUnlockAllowedByDevice() {
        final Integer[] requestStatus = new Integer[1];
        final Boolean[] allowedByDevice = new Boolean[1];
 
        try {
            mOemLock.isOemUnlockAllowedByDevice((status, allowed) -> {
                requestStatus[0] = status;
                allowedByDevice[0] = allowed;
            });
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to get devie state from HAL");
            throw e.rethrowFromSystemServer();
        }
 
        switch (requestStatus[0]) {
            case OemLockStatus.OK:
                // Success
                return allowedByDevice[0];
 
            default:
                Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL");
                // Fallthrough
            case OemLockStatus.FAILED:
                throw new RuntimeException("Failed to get device OEM unlock state");
        }
    }
 
    private ArrayList<Byte> toByteArrayList(byte[] data) {
        if (data == null) {
            return new ArrayList<Byte>();
        }
        ArrayList<Byte> result = new ArrayList<Byte>(data.length);
        for (final byte b : data) {
            result.add(b);
        }
        return result;
    }
}