1 /* 2 * Copyright (C) 2019 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.car.storagemonitoring; 17 18 import android.annotation.Nullable; 19 import android.annotation.TestApi; 20 import android.car.builtin.util.Slogf; 21 import android.hardware.health.V2_0.IHealth; 22 import android.hardware.health.V2_0.Result; 23 import android.hardware.health.V2_0.StorageInfo; 24 import android.os.RemoteException; 25 import android.util.MutableInt; 26 27 import com.android.car.CarLog; 28 29 import java.util.ArrayList; 30 import java.util.Arrays; 31 import java.util.List; 32 import java.util.NoSuchElementException; 33 34 /** 35 * Loads wear information from the Health service. 36 */ 37 public class HealthServiceWearInfoProvider implements WearInformationProvider { 38 39 private static final String INSTANCE_HEALTHD = "backup"; 40 private static final String INSTANCE_VENDOR = "default"; 41 42 private static final List<String> sAllInstances = 43 Arrays.asList(INSTANCE_VENDOR, INSTANCE_HEALTHD); 44 45 private IHealthSupplier mHealthSupplier; 46 HealthServiceWearInfoProvider()47 public HealthServiceWearInfoProvider() { 48 mHealthSupplier = new IHealthSupplier() {}; 49 } 50 51 @Nullable 52 @Override load()53 public WearInformation load() { 54 IHealth healthService = getHealthService(); 55 final MutableInt success = new MutableInt(Result.NOT_SUPPORTED); 56 final MutableInt foundInternalStorageDeviceInfo = new MutableInt(0); 57 final MutableInt lifetimeA = new MutableInt(0); 58 final MutableInt lifetimeB = new MutableInt(0); 59 final MutableInt preEol = new MutableInt(0); 60 61 final IHealth.getStorageInfoCallback getStorageInfoCallbackImpl = 62 new IHealth.getStorageInfoCallback() { 63 @Override 64 public void onValues(int result, ArrayList<StorageInfo> value) { 65 success.value = result; 66 if (result == Result.SUCCESS) { 67 int len = value.size(); 68 for (int i = 0; i < len; i++) { 69 StorageInfo value2 = value.get(i); 70 if (value2.attr.isInternal) { 71 lifetimeA.value = value2.lifetimeA; 72 lifetimeB.value = value2.lifetimeB; 73 preEol.value = value2.eol; 74 foundInternalStorageDeviceInfo.value = 1; 75 } 76 } 77 } 78 }}; 79 80 if (healthService == null) { 81 Slogf.w(CarLog.TAG_STORAGE, 82 "No health service is available to fetch wear information."); 83 return null; 84 } 85 86 try { 87 healthService.getStorageInfo(getStorageInfoCallbackImpl); 88 } catch (Exception e) { 89 Slogf.w(CarLog.TAG_STORAGE, "Failed to get storage information from" 90 + "health service, exception :" + e); 91 return null; 92 } 93 94 if (success.value != Result.SUCCESS) { 95 Slogf.w(CarLog.TAG_STORAGE, "Health service returned result :" + success.value); 96 return null; 97 } else if (foundInternalStorageDeviceInfo.value == 0) { 98 Slogf.w(CarLog.TAG_STORAGE, "Failed to find storage information for" 99 + "internal storage device"); 100 return null; 101 } else { 102 return new WearInformation(convertLifetime(lifetimeA.value), 103 convertLifetime(lifetimeB.value), preEol.value); 104 } 105 } 106 107 @Nullable getHealthService()108 private IHealth getHealthService() { 109 for (String name : sAllInstances) { 110 IHealth newService = null; 111 try { 112 newService = mHealthSupplier.get(name); 113 } catch (Exception e) { 114 /* ignored, handled below */ 115 } 116 if (newService != null) { 117 return newService; 118 } 119 } 120 return null; 121 } 122 123 @TestApi setHealthSupplier(IHealthSupplier healthSupplier)124 public void setHealthSupplier(IHealthSupplier healthSupplier) { 125 mHealthSupplier = healthSupplier; 126 } 127 128 /** 129 * Supplier of services. 130 * Must not return null; throw {@link NoSuchElementException} if a service is not available. 131 */ 132 interface IHealthSupplier { get(String name)133 default IHealth get(String name) throws NoSuchElementException, RemoteException { 134 return IHealth.getService(name, false /* retry */); 135 } 136 } 137 } 138