blob: dfbef8a768bd1ed467c02ae61defa5f882c0954e [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.os.cts;
import android.os.Environment;
import android.platform.test.annotations.AppModeFull;
import android.system.Os;
import android.system.StructStatVfs;
import junit.framework.TestCase;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
public class EnvironmentTest extends TestCase {
public void testEnvironment() {
new Environment();
assertNotNull(Environment.getExternalStorageState());
assertTrue(Environment.getRootDirectory().isDirectory());
assertTrue(Environment.getDownloadCacheDirectory().isDirectory());
assertTrue(Environment.getDataDirectory().isDirectory());
}
@AppModeFull(reason = "External directory not accessible by instant apps")
public void testEnvironmentExternal() {
assertTrue(Environment.getExternalStorageDirectory().isDirectory());
}
/**
* TMPDIR being set prevents apps from asking to have temporary files
* placed in their own storage, instead forcing their location to
* something OS-defined. If TMPDIR points to a global shared directory,
* this could compromise the security of the files.
*/
public void testNoTmpDir() {
assertNull("environment variable TMPDIR should not be set",
System.getenv("TMPDIR"));
}
/**
* Verify that all writable block filesystems are mounted "noatime" to avoid
* unnecessary flash churn.
*/
public void testNoAtime() throws Exception {
try (BufferedReader br = new BufferedReader(new FileReader("/proc/mounts"))) {
String line;
while ((line = br.readLine()) != null) {
final String[] fields = line.split(" ");
final String source = fields[0];
final String options = fields[3];
if (source.startsWith("/dev/block/") && !options.startsWith("ro,")
&& !options.contains("noatime")) {
fail("Found device mounted at " + source + " without 'noatime' option, "
+ "which can cause unnecessary flash churn; please update your fstab.");
}
}
}
}
/**
* verify hidepid=2 on /proc
*/
public void testHidePid2() throws Exception {
try (BufferedReader br = new BufferedReader(new FileReader("/proc/mounts"))) {
String line;
while ((line = br.readLine()) != null) {
final String[] fields = line.split(" ");
final String source = fields[0];
final String options = fields[3];
if (source.equals("proc") && !options.contains("hidepid=2")) {
fail("proc filesystem mounted without hidepid=2");
}
}
}
}
public void testHidePid2_direct() throws Exception {
assertFalse(new File("/proc/1").exists());
}
/**
* Verify that all writable block filesystems are mounted with "resgid" to
* mitigate disk-full trouble.
*/
public void testSaneInodes() throws Exception {
final File file = Environment.getDataDirectory();
final StructStatVfs stat = Os.statvfs(file.getAbsolutePath());
// By default ext4 creates one inode per 16KiB; we're okay with a much
// wider range, but we want to make sure the device isn't going totally
// crazy; too few inodes can result in system instability, and too many
// inodes can result in wasted space.
final long maxsize = stat.f_blocks * stat.f_frsize;
final long maxInodes = maxsize / 4096;
// Assuming the smallest storage would be 4GB, min # of free inodes
// in EXT4/F2FS must be larger than 128k for Android to work properly.
final long minInodes = 128 * 1024;
if (stat.f_ffree >= minInodes && stat.f_ffree <= maxInodes
&& stat.f_favail <= stat.f_ffree) {
// Sweet, sounds great!
} else {
fail("Number of inodes " + stat.f_ffree + "/" + stat.f_favail
+ " not within sane range for partition of " + maxsize + " bytes; expected ["
+ minInodes + "," + maxInodes + "]");
}
}
}