1 /* 2 * Copyright (C) 2022 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 android.adservices.ondevicepersonalization; 18 19 import android.adservices.ondevicepersonalization.aidl.IDataAccessService; 20 import android.adservices.ondevicepersonalization.aidl.IDataAccessServiceCallback; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.os.Bundle; 24 import android.os.RemoteException; 25 26 import com.android.ondevicepersonalization.internal.util.ByteArrayParceledSlice; 27 import com.android.ondevicepersonalization.internal.util.LoggerFactory; 28 29 import java.util.Collections; 30 import java.util.HashSet; 31 import java.util.Objects; 32 import java.util.Set; 33 import java.util.concurrent.ArrayBlockingQueue; 34 import java.util.concurrent.BlockingQueue; 35 36 /** @hide */ 37 public class RemoteDataImpl implements KeyValueStore { 38 private static final LoggerFactory.Logger sLogger = LoggerFactory.getLogger(); 39 private static final String TAG = "RemoteDataImpl"; 40 @NonNull 41 IDataAccessService mDataAccessService; 42 43 /** @hide */ RemoteDataImpl(@onNull IDataAccessService binder)44 public RemoteDataImpl(@NonNull IDataAccessService binder) { 45 mDataAccessService = Objects.requireNonNull(binder); 46 } 47 48 @Override @Nullable get(@onNull String key)49 public byte[] get(@NonNull String key) { 50 Objects.requireNonNull(key); 51 final long startTimeMillis = System.currentTimeMillis(); 52 int responseCode = Constants.STATUS_SUCCESS; 53 try { 54 BlockingQueue<Bundle> asyncResult = new ArrayBlockingQueue<>(1); 55 Bundle params = new Bundle(); 56 params.putString(Constants.EXTRA_LOOKUP_KEYS, key); 57 mDataAccessService.onRequest( 58 Constants.DATA_ACCESS_OP_REMOTE_DATA_LOOKUP, 59 params, 60 new IDataAccessServiceCallback.Stub() { 61 @Override 62 public void onSuccess(@NonNull Bundle result) { 63 if (result != null) { 64 asyncResult.add(result); 65 } else { 66 asyncResult.add(Bundle.EMPTY); 67 } 68 } 69 70 @Override 71 public void onError(int errorCode) { 72 asyncResult.add(Bundle.EMPTY); 73 } 74 }); 75 Bundle result = asyncResult.take(); 76 ByteArrayParceledSlice data = result.getParcelable( 77 Constants.EXTRA_RESULT, ByteArrayParceledSlice.class); 78 return (data == null) ? null : data.getByteArray(); 79 } catch (InterruptedException | RemoteException e) { 80 sLogger.e(TAG + ": Failed to retrieve key from remoteData", e); 81 responseCode = Constants.STATUS_INTERNAL_ERROR; 82 throw new IllegalStateException(e); 83 } finally { 84 try { 85 mDataAccessService.logApiCallStats( 86 Constants.API_NAME_REMOTE_DATA_GET, 87 System.currentTimeMillis() - startTimeMillis, 88 responseCode); 89 } catch (Exception e) { 90 sLogger.d(e, TAG + ": failed to log metrics"); 91 } 92 } 93 } 94 95 @Override @NonNull keySet()96 public Set<String> keySet() { 97 final long startTimeMillis = System.currentTimeMillis(); 98 int responseCode = Constants.STATUS_SUCCESS; 99 try { 100 BlockingQueue<Bundle> asyncResult = new ArrayBlockingQueue<>(1); 101 mDataAccessService.onRequest( 102 Constants.DATA_ACCESS_OP_REMOTE_DATA_KEYSET, 103 Bundle.EMPTY, 104 new IDataAccessServiceCallback.Stub() { 105 @Override 106 public void onSuccess(@NonNull Bundle result) { 107 if (result != null) { 108 asyncResult.add(result); 109 } else { 110 asyncResult.add(Bundle.EMPTY); 111 } 112 } 113 114 @Override 115 public void onError(int errorCode) { 116 asyncResult.add(Bundle.EMPTY); 117 } 118 }); 119 Bundle result = asyncResult.take(); 120 HashSet<String> resultSet = 121 result.getSerializable(Constants.EXTRA_RESULT, HashSet.class); 122 if (null == resultSet) { 123 return Collections.emptySet(); 124 } 125 return resultSet; 126 } catch (InterruptedException | RemoteException e) { 127 sLogger.e(TAG + ": Failed to retrieve keySet from remoteData", e); 128 throw new IllegalStateException(e); 129 } finally { 130 try { 131 mDataAccessService.logApiCallStats( 132 Constants.API_NAME_REMOTE_DATA_KEYSET, 133 System.currentTimeMillis() - startTimeMillis, 134 responseCode); 135 } catch (Exception e) { 136 sLogger.d(e, TAG + ": failed to log metrics"); 137 } 138 } 139 } 140 141 @Override getTableId()142 public int getTableId() { 143 return ModelId.TABLE_ID_REMOTE_DATA; 144 } 145 } 146