1 /* 2 * Copyright 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 17 package com.android.tv.common.util; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.media.tv.TvInputInfo; 22 import android.os.Build; 23 import android.util.ArraySet; 24 import android.util.Log; 25 import com.android.tv.common.CommonConstants; 26 import com.android.tv.common.actions.InputSetupActionUtils; 27 import java.io.File; 28 import java.text.SimpleDateFormat; 29 import java.util.Date; 30 import java.util.Locale; 31 import java.util.Set; 32 33 /** Util class for common use in TV app and inputs. */ 34 @SuppressWarnings("AndroidApiChecker") // TODO(b/32513850) remove when error prone is updated 35 public final class CommonUtils { 36 private static final String TAG = "CommonUtils"; 37 private static final ThreadLocal<SimpleDateFormat> ISO_8601 = 38 new ThreadLocal() { 39 private final SimpleDateFormat value = 40 new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US); 41 42 @Override 43 protected SimpleDateFormat initialValue() { 44 return value; 45 } 46 }; 47 // Hardcoded list for known bundled inputs not written by OEM/SOCs. 48 // Bundled (system) inputs not in the list will get the high priority 49 // so they and their channels come first in the UI. 50 private static final Set<String> BUNDLED_PACKAGE_SET = new ArraySet<>(); 51 52 static { 53 BUNDLED_PACKAGE_SET.add("com.android.tv"); 54 // AOSP_Comment_Out BUNDLED_PACKAGE_SET.add(CommonConstants.BASE_PACKAGE); 55 } 56 57 private static Boolean sRunningInTest; 58 CommonUtils()59 private CommonUtils() {} 60 61 /** 62 * Returns an intent to start the setup activity for the TV input using {@link 63 * InputSetupActionUtils#INTENT_ACTION_INPUT_SETUP}. 64 */ createSetupIntent(Intent originalSetupIntent, String inputId)65 public static Intent createSetupIntent(Intent originalSetupIntent, String inputId) { 66 if (originalSetupIntent == null) { 67 return null; 68 } 69 Intent setupIntent = new Intent(originalSetupIntent); 70 if (!InputSetupActionUtils.hasInputSetupAction(originalSetupIntent)) { 71 Intent intentContainer = new Intent(InputSetupActionUtils.INTENT_ACTION_INPUT_SETUP); 72 intentContainer.putExtra(InputSetupActionUtils.EXTRA_SETUP_INTENT, originalSetupIntent); 73 intentContainer.putExtra(InputSetupActionUtils.EXTRA_INPUT_ID, inputId); 74 setupIntent = intentContainer; 75 } 76 return setupIntent; 77 } 78 79 /** 80 * Returns an intent to start the setup activity for this TV input using {@link 81 * InputSetupActionUtils#INTENT_ACTION_INPUT_SETUP}. 82 */ createSetupIntent(TvInputInfo input)83 public static Intent createSetupIntent(TvInputInfo input) { 84 return createSetupIntent(input.createSetupIntent(), input.getId()); 85 } 86 87 /** 88 * Checks if this application is running in tests. 89 * 90 * <p>{@link android.app.ActivityManager#isRunningInTestHarness} doesn't return {@code true} for 91 * the usual devices even the application is running in tests. We need to figure it out by 92 * checking whether the class in tv-tests-common module can be loaded or not. 93 */ isRunningInTest()94 public static synchronized boolean isRunningInTest() { 95 if (sRunningInTest == null) { 96 try { 97 Class.forName("com.android.tv.testing.utils.Utils"); 98 Log.i( 99 TAG, 100 "Assumed to be running in a test because" 101 + " com.android.tv.testing.utils.Utils is found"); 102 sRunningInTest = true; 103 } catch (ClassNotFoundException e) { 104 sRunningInTest = false; 105 } 106 } 107 return sRunningInTest; 108 } 109 110 /** Checks whether a given package is in our bundled package set. */ isInBundledPackageSet(String packageName)111 public static boolean isInBundledPackageSet(String packageName) { 112 return BUNDLED_PACKAGE_SET.contains(packageName); 113 } 114 115 /** Checks whether a given input is a bundled input. */ isBundledInput(String inputId)116 public static boolean isBundledInput(String inputId) { 117 for (String prefix : BUNDLED_PACKAGE_SET) { 118 if (inputId.startsWith(prefix + "/")) { 119 return true; 120 } 121 } 122 return false; 123 } 124 125 /** Returns true if the application is packaged with TV app. */ isPackagedWithLiveChannels(Context context)126 public static boolean isPackagedWithLiveChannels(Context context) { 127 return (CommonConstants.BASE_PACKAGE.equals(context.getPackageName())); 128 } 129 130 /** Converts time in milliseconds to a ISO 8061 string. */ toIsoDateTimeString(long timeMillis)131 public static String toIsoDateTimeString(long timeMillis) { 132 return ISO_8601.get().format(new Date(timeMillis)); 133 } 134 135 /** 136 * Deletes a file or a directory. 137 * 138 * @return <code>true</code> if and only if the file or directory is successfully deleted; 139 * <code>false</code> otherwise 140 */ deleteDirOrFile(File fileOrDirectory)141 public static boolean deleteDirOrFile(File fileOrDirectory) { 142 if (fileOrDirectory.isDirectory()) { 143 File[] files = fileOrDirectory.listFiles(); 144 if (files != null) { 145 for (File child : files) { 146 deleteDirOrFile(child); 147 } 148 } 149 } 150 // If earlier deletes failed this will also 151 return fileOrDirectory.delete(); 152 } 153 isRoboTest()154 public static boolean isRoboTest() { 155 return "robolectric".equals(Build.FINGERPRINT); 156 } 157 } 158