blob: 0d5b17b828b87170ca8fc9a03e6c052d44410954 [file] [log] [blame]
Chad Brubaker40a1a9b2015-02-20 14:08:13 -08001/*
2 * Copyright (C) 2015 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#define LOG_TAG "KeystoreOperation"
17
18#include "operation.h"
19
20#include <algorithm>
21
22namespace android {
23OperationMap::OperationMap(IBinder::DeathRecipient* deathRecipient)
24 : mDeathRecipient(deathRecipient) {
25}
26
27sp<IBinder> OperationMap::addOperation(keymaster_operation_handle_t handle,
28 const keymaster1_device_t* dev,
29 sp<IBinder> appToken, bool pruneable) {
30 sp<IBinder> token = new BBinder();
31 mMap[token] = Operation(handle, dev, appToken);
32 if (pruneable) {
33 mLru.push_back(token);
34 }
35 if (mAppTokenMap.find(appToken) == mAppTokenMap.end()) {
36 appToken->linkToDeath(mDeathRecipient);
37 }
38 mAppTokenMap[appToken].push_back(token);
39 return token;
40}
41
42bool OperationMap::getOperation(sp<IBinder> token, keymaster_operation_handle_t* outHandle,
43 const keymaster1_device_t** outDevice) {
44 if (!outHandle || !outDevice) {
45 return false;
46 }
47 auto entry = mMap.find(token);
48 if (entry == mMap.end()) {
49 return false;
50 }
51 updateLru(token);
52
53 *outHandle = entry->second.handle;
54 *outDevice = entry->second.device;
55 return true;
56}
57
58void OperationMap::updateLru(sp<IBinder> token) {
59 auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
60 if (lruEntry != mLru.end()) {
61 mLru.erase(lruEntry);
62 mLru.push_back(token);
63 }
64}
65
66bool OperationMap::removeOperation(sp<IBinder> token) {
67 auto entry = mMap.find(token);
68 if (entry == mMap.end()) {
69 return false;
70 }
71 sp<IBinder> appToken = entry->second.appToken;
72 mMap.erase(entry);
73 auto lruEntry = std::find(mLru.begin(), mLru.end(), token);
74 if (lruEntry != mLru.end()) {
75 mLru.erase(lruEntry);
76 }
77 removeOperationTracking(token, appToken);
78 return true;
79}
80
81void OperationMap::removeOperationTracking(sp<IBinder> token, sp<IBinder> appToken) {
82 auto appEntry = mAppTokenMap.find(appToken);
83 if (appEntry == mAppTokenMap.end()) {
84 ALOGE("Entry for %p contains unmapped application token %p", token.get(), appToken.get());
85 return;
86 }
87 auto tokenEntry = std::find(appEntry->second.begin(), appEntry->second.end(), token);
88 appEntry->second.erase(tokenEntry);
89 // Stop listening for death if all operations tied to the token have finished.
90 if (appEntry->second.size() == 0) {
91 appToken->unlinkToDeath(mDeathRecipient);
92 mAppTokenMap.erase(appEntry);
93 }
94}
95
96bool OperationMap::hasPruneableOperation() {
97 return mLru.size() != 0;
98}
99
100sp<IBinder> OperationMap::getOldestPruneableOperation() {
101 if (!hasPruneableOperation()) {
102 return sp<IBinder>(NULL);
103 }
104 return mLru[0];
105}
106
107std::vector<sp<IBinder>> OperationMap::getOperationsForToken(sp<IBinder> appToken) {
108 auto appEntry = mAppTokenMap.find(appToken);
109 if (appEntry != mAppTokenMap.end()) {
110 return appEntry->second;
111 } else {
112 return std::vector<sp<IBinder>>();
113 }
114}
115
116OperationMap::Operation::Operation(keymaster_operation_handle_t handle_,
117 const keymaster1_device_t* device_,
118 sp<IBinder> appToken_)
119 : handle(handle_),
120 device(device_),
121 appToken(appToken_) {
122}
123
124OperationMap::Operation::Operation() : handle(0), device(NULL), appToken(NULL) {
125}
126} // namespace android