AOSP系统框架可以对外部存储具有读/写访问权限吗?

时间:2018-07-04 19:59:45

标签: android android-source android-external-storage

众所周知,只要声明或请求适当的权限然后再授予其权限,Android应用程序(无论是用户应用程序还是系统应用程序)都可以访问外部存储。例如,为了访问通过调用获得的外部存储的Downloads目录:

Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);

以下读取/写入权限需要在文件“ AndroidManifest.xml”中声明:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

对于Android M及更高版本,在尝试访问外部存储设备之前,必须发出并授予存储权限的其他运行时请求,否则尝试创建文件输入/输出流将导致以下系统错误:

w/System_err: java.io.FileNotFoundException: /storage/emulated/0/Download/<file name> (Permission denied).

现在我的问题是,AOSP系统框架(不是Android应用程序,因此没有关联的“ AndroidManifest.xml”文件)也可以对外部存储设备具有读/写访问权限吗?

我最初的猜测是肯定的,因为系统框架应允许自己访问文件系统而无需询问权限。但是,我的测试结果表明,上面的“权限被拒绝”系统错误已发出。为了证明这一点,我创建了以下简单的Java文件I / O测试方法:

public void testFileIO(final String file1Name, final String file2Name, final String fileContent) {
  Log.d(TAG, "testFileIO: fil1Name=[" + file1Name + "], file2Name=[" + file2Name + "], fileContent=[" + fileContent + "]");

  try {
    // This line is required for system framework modules to avoid a warning:
    //Environment.setUserRequired(false);

    File parentDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
    if (!parentDir.exists()) {
      boolean dirCreated = parentDir.mkdirs();
      Log.w(TAG, "testFileIO: parentDir=[" + parentDir.getPath() + "] did not exist. dirCreate=[" + dirCreated + "]");
    }

    File file1 = new File(parentDir, file1Name);
    if (file1.exists()) {
      boolean file1Deleted = file1.delete();
      Log.w(TAG, "testFileIO: file1=[" + file1.getPath() + "] existed. file1Deleted=[" + file1Deleted + "]");
    }

    File file2 = new File(parentDir, file2Name);
    if (file2.exists()) {
      boolean file2Deleted = file2.delete();
      Log.w(TAG, "testFileIO: file2=[" + file2.getPath() + "] existed. file2Deleted=[" + file2Deleted + "]");
    }

    // Create file1:

    // !!! May result in “Permission denied” system error in some cases:
    FileOutputStream fos1 = new FileOutputStream(file1, false);

    byte[] contentBytes = fileContent.getBytes();
    fos1.write(contentBytes);
    fos1.flush();
    fos1.close();

    // Copy file1 to file2:

    FileInputStream fis1 = new FileInputStream(file1);
    FileOutputStream fos2 = new FileOutputStream(file2, false);

    int len;
    byte[] buffer = new byte[1024];

    while ((len = fis1.read(buffer)) != -1) {
      fos2.write(buffer, 0, len);
    }

    fos2.flush();
    fos2.close();
    fis1.close();

    // Check results:

    Log.v(TAG, "testFileIO: file1.path=[" + file1.getPath() + "]");
    Log.v(TAG, "testFileIO: file1.length=[" + file1.length() + "]");
    Log.v(TAG, "testFileIO: file2.path=[" + file2.getPath() + "]");
    Log.v(TAG, "testFileIO: file2.length=[" + file2.length() + "]");
  } catch (IOException e){
    e.printStackTrace();
  }

  Log.v(TAG, "testFileIO: end");
}

此方法尝试在外部存储的Downloads目录中创建第一个文件,然后将其内容复制到同一目录中的第二个文件中。

当我从系统服务(例如ConnectivityService)(通过修改AOSP源代码)调用此方法时,在触发系统广播Intent CONNECTIVITY_ACTION的那一刻,执行以下命令时会出现上述“权限被拒绝”的系统错误消息以下行:

FileOutputStream fos1 = new FileOutputStream(file1, false);

为什么会这样?以及如何允许ConnectivityService(或其他系统框架模块)对外部存储具有读/写访问权限?预先感谢您的回答。

0 个答案:

没有答案