1 /* 2 * Copyright (C) 2021 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.bugreport; 17 18 import android.app.ActivityThread; 19 import android.os.Build; 20 import android.os.SystemProperties; 21 import android.provider.DeviceConfig; 22 import android.util.Log; 23 24 import com.android.internal.annotations.GuardedBy; 25 26 import com.google.common.collect.ImmutableSet; 27 28 import java.io.PrintWriter; 29 30 /** 31 * Contains config for BugReport App. 32 * 33 * <p>The config is kept synchronized with {@code car} namespace. It's not defined in 34 * {@link DeviceConfig}. 35 * 36 * <ul>To get/set the flags via adb: 37 * <li>{@code adb shell device_config get car bugreport_upload_destination} 38 * <li>{@code adb shell device_config put car bugreport_upload_destination gcs} 39 * <li>{@code adb shell device_config delete car bugreport_upload_destination} 40 * </ul> 41 */ 42 final class Config { 43 private static final String TAG = Config.class.getSimpleName(); 44 45 /** 46 * Namespace for all Android Automotive related features. 47 * 48 * <p>In the future it will move to {@code DeviceConfig#NAMESPACE_CAR}. 49 */ 50 private static final String NAMESPACE_CAR = "car"; 51 52 /** 53 * A string flag, can be one of {@code null} or {@link #UPLOAD_DESTINATION_GCS}. 54 */ 55 private static final String KEY_BUGREPORT_UPLOAD_DESTINATION = "bugreport_upload_destination"; 56 57 /** 58 * A value for {@link #KEY_BUGREPORT_UPLOAD_DESTINATION}. 59 * 60 * Upload bugreports to GCS. Only works in {@code userdebug} or {@code eng} builds. 61 */ 62 private static final String UPLOAD_DESTINATION_GCS = "gcs"; 63 64 /** 65 * A system property to force enable the app bypassing the {@code userdebug/eng} build check. 66 */ 67 private static final String PROP_FORCE_ENABLE = "android.car.bugreport.force_enable"; 68 69 /** 70 * A system property to override GCS bucket name that is defined in {@code configs.xml}. 71 */ 72 73 private static final String PROP_GCS_BUCKET = "android.car.bugreport.gcs_bucket"; 74 75 /* 76 * Enable uploading new bugreports to GCS for these devices. If the device is not in this list, 77 * {@link #KEY_UPLOAD_DESTINATION} flag will be used instead. 78 */ 79 private static final ImmutableSet<String> ENABLE_FORCE_UPLOAD_TO_GCS_FOR_DEVICES = 80 ImmutableSet.of("hawk", "seahawk"); 81 82 private final Object mLock = new Object(); 83 84 @GuardedBy("mLock") 85 private String mUploadDestination = null; 86 create()87 static Config create() { 88 Config config = new Config(); 89 config.start(); 90 return config; 91 } 92 Config()93 private Config() {} 94 start()95 private void start() { 96 DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_CAR, 97 ActivityThread.currentApplication().getMainExecutor(), this::onPropertiesChanged); 98 updateConstants(); 99 } 100 onPropertiesChanged(DeviceConfig.Properties properties)101 private void onPropertiesChanged(DeviceConfig.Properties properties) { 102 if (properties.getKeyset().contains(KEY_BUGREPORT_UPLOAD_DESTINATION)) { 103 updateConstants(); 104 } 105 } 106 107 /** Returns true if bugreport app is enabled for this device. */ isBugReportEnabled()108 static boolean isBugReportEnabled() { 109 return Build.IS_DEBUGGABLE || SystemProperties.getBoolean(PROP_FORCE_ENABLE, false); 110 } 111 112 /** Returns GCS bucket system property. */ getPropGcsBucket()113 static String getPropGcsBucket() { 114 return SystemProperties.get(PROP_GCS_BUCKET, ""); 115 } 116 117 /** If new bugreports should be scheduled for uploading. */ isAutoUpload()118 boolean isAutoUpload() { 119 // TODO(b/144851443): Enable auto-upload only if upload destination is Gcs until 120 // we create a way to allow implementing OEMs custom upload logic. 121 return isUploadDestinationGcs(); 122 } 123 124 /** 125 * Returns {@link true} if bugreport upload destination is GCS. 126 */ isUploadDestinationGcs()127 private boolean isUploadDestinationGcs() { 128 if (isTempForceAutoUploadGcsEnabled()) { 129 Log.d(TAG, "Setting upload dest to GCS ENABLE_AUTO_UPLOAD is true"); 130 return true; 131 } 132 // NOTE: enable it only for userdebug/eng builds. 133 return UPLOAD_DESTINATION_GCS.equals(getUploadDestination()) && Build.IS_DEBUGGABLE; 134 } 135 isTempForceAutoUploadGcsEnabled()136 private static boolean isTempForceAutoUploadGcsEnabled() { 137 return ENABLE_FORCE_UPLOAD_TO_GCS_FOR_DEVICES.contains(Build.DEVICE); 138 } 139 140 /** 141 * Returns value of a flag {@link #KEY_BUGREPORT_UPLOAD_DESTINATION}. 142 */ getUploadDestination()143 private String getUploadDestination() { 144 synchronized (mLock) { 145 return mUploadDestination; 146 } 147 } 148 updateConstants()149 private void updateConstants() { 150 synchronized (mLock) { 151 mUploadDestination = DeviceConfig.getString(NAMESPACE_CAR, 152 KEY_BUGREPORT_UPLOAD_DESTINATION, /* defaultValue= */ null); 153 } 154 } 155 dump(String prefix, PrintWriter pw)156 void dump(String prefix, PrintWriter pw) { 157 pw.println(prefix + "car.bugreport.Config:"); 158 159 pw.print(prefix + " "); 160 pw.print("getAutoUpload"); 161 pw.print("="); 162 pw.println(isAutoUpload() ? "true" : "false"); 163 164 pw.print(prefix + " "); 165 pw.print("getUploadDestination"); 166 pw.print("="); 167 pw.println(getUploadDestination()); 168 169 pw.print(prefix + " "); 170 pw.print("isUploadDestinationGcs"); 171 pw.print("="); 172 pw.println(isUploadDestinationGcs()); 173 } 174 } 175