Loading core/java/android/app/backup/BackupAgent.java +3 −30 Original line number Diff line number Diff line Loading @@ -43,7 +43,6 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Collection; import java.util.LinkedList; import java.util.Map; import java.util.Set; Loading Loading @@ -833,7 +832,7 @@ public abstract class BackupAgent extends ContextWrapper { } if (excludes != null && isFileSpecifiedInPathList(destination, excludes)) { BackupUtils.isFileSpecifiedInPathList(destination, excludes)) { if (Log.isLoggable(FullBackup.TAG_XML_PARSER, Log.VERBOSE)) { Log.v(FullBackup.TAG_XML_PARSER, "onRestoreFile: \"" + destinationCanonicalPath + "\": listed in" Loading @@ -847,7 +846,8 @@ public abstract class BackupAgent extends ContextWrapper { // it's a small list), we'll go through and look for it. boolean explicitlyIncluded = false; for (Set<PathWithRequiredFlags> domainIncludes : includes.values()) { explicitlyIncluded |= isFileSpecifiedInPathList(destination, domainIncludes); explicitlyIncluded |= BackupUtils.isFileSpecifiedInPathList(destination, domainIncludes); if (explicitlyIncluded) { break; } Loading @@ -865,33 +865,6 @@ public abstract class BackupAgent extends ContextWrapper { return true; } /** * @return True if the provided file is either directly in the provided list, or the provided * file is within a directory in the list. */ private boolean isFileSpecifiedInPathList(File file, Collection<PathWithRequiredFlags> canonicalPathList) throws IOException { for (PathWithRequiredFlags canonical : canonicalPathList) { String canonicalPath = canonical.getPath(); File fileFromList = new File(canonicalPath); if (fileFromList.isDirectory()) { if (file.isDirectory()) { // If they are both directories check exact equals. return file.equals(fileFromList); } else { // O/w we have to check if the file is within the directory from the list. return file.getCanonicalPath().startsWith(canonicalPath); } } else { if (file.equals(fileFromList)) { // Need to check the explicit "equals" so we don't end up with substrings. return true; } } } return false; } /** * Only specialized platform agents should overload this entry point to support * restores to crazy non-app locations. Loading core/java/android/app/backup/BackupUtils.java 0 → 100644 +58 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.app.backup; import android.app.backup.FullBackup.BackupScheme.PathWithRequiredFlags; import java.io.File; import java.io.IOException; import java.util.Collection; /** @hide */ public class BackupUtils { private BackupUtils() {} /** * Returns {@code true} if {@code file} is either directly in {@code canonicalPathList} or is a * file contained in a directory in the list. */ public static boolean isFileSpecifiedInPathList( File file, Collection<PathWithRequiredFlags> canonicalPathList) throws IOException { for (PathWithRequiredFlags canonical : canonicalPathList) { String canonicalPath = canonical.getPath(); File fileFromList = new File(canonicalPath); if (fileFromList.isDirectory()) { if (file.isDirectory()) { // If they are both directories check exact equals. if (file.equals(fileFromList)) { return true; } } else { // O/w we have to check if the file is within the directory from the list. if (file.toPath().startsWith(canonicalPath)) { return true; } } } else if (file.equals(fileFromList)) { // Need to check the explicit "equals" so we don't end up with substrings. return true; } } return false; } } services/robotests/src/android/app/backup/BackupUtilsTest.java 0 → 100644 +195 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.app.backup; import static com.google.common.truth.Truth.assertThat; import android.app.backup.FullBackup.BackupScheme.PathWithRequiredFlags; import android.content.Context; import android.platform.test.annotations.Presubmit; import com.android.server.testing.FrameworkRobolectricTestRunner; import com.android.server.testing.SystemLoaderPackages; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.annotation.internal.DoNotInstrument; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.stream.Collectors; import java.util.stream.Stream; @RunWith(FrameworkRobolectricTestRunner.class) @Config(manifest = Config.NONE, sdk = 26) @SystemLoaderPackages({"android.app.backup"}) @Presubmit @DoNotInstrument public class BackupUtilsTest { private Context mContext; @Before public void setUp() throws Exception { mContext = RuntimeEnvironment.application; } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListHasIt() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(file("a/b.txt"), paths(file("a/b.txt"))); assertThat(isSpecified).isTrue(); } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListHasItsDirectory() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(file("a/b.txt"), paths(directory("a"))); assertThat(isSpecified).isTrue(); } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListHasOtherFile() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(file("a/b.txt"), paths(file("a/c.txt"))); assertThat(isSpecified).isFalse(); } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListEmpty() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(file("a/b.txt"), paths()); assertThat(isSpecified).isFalse(); } @Test public void testIsFileSpecifiedInPathList_whenDirectoryAndPathListHasIt() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(directory("a"), paths(directory("a"))); assertThat(isSpecified).isTrue(); } @Test public void testIsFileSpecifiedInPathList_whenDirectoryAndPathListEmpty() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(directory("a"), paths()); assertThat(isSpecified).isFalse(); } @Test public void testIsFileSpecifiedInPathList_whenDirectoryAndPathListHasParent() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(directory("a/b"), paths(directory("a"))); assertThat(isSpecified).isFalse(); } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListDoesntContainDirectory() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(file("a/b.txt"), paths(directory("c"))); assertThat(isSpecified).isFalse(); } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListHasDirectoryWhoseNameIsPrefix() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(file("a/b.txt"), paths(directory("a/b"))); assertThat(isSpecified).isFalse(); } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListHasDirectoryWhoseNameIsPrefix2() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList( file("name/subname.txt"), paths(directory("nam"))); assertThat(isSpecified).isFalse(); } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListContainsFirstNotRelatedAndSecondContainingDirectory() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList( file("a/b.txt"), paths(directory("b"), directory("a"))); assertThat(isSpecified).isTrue(); } @Test public void testIsFileSpecifiedInPathList_whenDirectoryAndPathListContainsFirstNotRelatedAndSecondSameDirectory() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList( directory("a/b"), paths(directory("b"), directory("a/b"))); assertThat(isSpecified).isTrue(); } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListContainsFirstNotRelatedFileAndSecondSameFile() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList( file("a/b.txt"), paths(directory("b"), file("a/b.txt"))); assertThat(isSpecified).isTrue(); } private File file(String path) throws IOException { File file = new File(mContext.getDataDir(), path); File parent = file.getParentFile(); parent.mkdirs(); file.createNewFile(); if (!file.isFile()) { throw new IOException("Couldn't create file"); } return file; } private File directory(String path) throws IOException { File directory = new File(mContext.getDataDir(), path); directory.mkdirs(); if (!directory.isDirectory()) { throw new IOException("Couldn't create directory"); } return directory; } private Collection<PathWithRequiredFlags> paths(File... files) { return Stream.of(files) .map(file -> new PathWithRequiredFlags(file.getPath(), 0)) .collect(Collectors.toList()); } } Loading
core/java/android/app/backup/BackupAgent.java +3 −30 Original line number Diff line number Diff line Loading @@ -43,7 +43,6 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Collection; import java.util.LinkedList; import java.util.Map; import java.util.Set; Loading Loading @@ -833,7 +832,7 @@ public abstract class BackupAgent extends ContextWrapper { } if (excludes != null && isFileSpecifiedInPathList(destination, excludes)) { BackupUtils.isFileSpecifiedInPathList(destination, excludes)) { if (Log.isLoggable(FullBackup.TAG_XML_PARSER, Log.VERBOSE)) { Log.v(FullBackup.TAG_XML_PARSER, "onRestoreFile: \"" + destinationCanonicalPath + "\": listed in" Loading @@ -847,7 +846,8 @@ public abstract class BackupAgent extends ContextWrapper { // it's a small list), we'll go through and look for it. boolean explicitlyIncluded = false; for (Set<PathWithRequiredFlags> domainIncludes : includes.values()) { explicitlyIncluded |= isFileSpecifiedInPathList(destination, domainIncludes); explicitlyIncluded |= BackupUtils.isFileSpecifiedInPathList(destination, domainIncludes); if (explicitlyIncluded) { break; } Loading @@ -865,33 +865,6 @@ public abstract class BackupAgent extends ContextWrapper { return true; } /** * @return True if the provided file is either directly in the provided list, or the provided * file is within a directory in the list. */ private boolean isFileSpecifiedInPathList(File file, Collection<PathWithRequiredFlags> canonicalPathList) throws IOException { for (PathWithRequiredFlags canonical : canonicalPathList) { String canonicalPath = canonical.getPath(); File fileFromList = new File(canonicalPath); if (fileFromList.isDirectory()) { if (file.isDirectory()) { // If they are both directories check exact equals. return file.equals(fileFromList); } else { // O/w we have to check if the file is within the directory from the list. return file.getCanonicalPath().startsWith(canonicalPath); } } else { if (file.equals(fileFromList)) { // Need to check the explicit "equals" so we don't end up with substrings. return true; } } } return false; } /** * Only specialized platform agents should overload this entry point to support * restores to crazy non-app locations. Loading
core/java/android/app/backup/BackupUtils.java 0 → 100644 +58 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.app.backup; import android.app.backup.FullBackup.BackupScheme.PathWithRequiredFlags; import java.io.File; import java.io.IOException; import java.util.Collection; /** @hide */ public class BackupUtils { private BackupUtils() {} /** * Returns {@code true} if {@code file} is either directly in {@code canonicalPathList} or is a * file contained in a directory in the list. */ public static boolean isFileSpecifiedInPathList( File file, Collection<PathWithRequiredFlags> canonicalPathList) throws IOException { for (PathWithRequiredFlags canonical : canonicalPathList) { String canonicalPath = canonical.getPath(); File fileFromList = new File(canonicalPath); if (fileFromList.isDirectory()) { if (file.isDirectory()) { // If they are both directories check exact equals. if (file.equals(fileFromList)) { return true; } } else { // O/w we have to check if the file is within the directory from the list. if (file.toPath().startsWith(canonicalPath)) { return true; } } } else if (file.equals(fileFromList)) { // Need to check the explicit "equals" so we don't end up with substrings. return true; } } return false; } }
services/robotests/src/android/app/backup/BackupUtilsTest.java 0 → 100644 +195 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.app.backup; import static com.google.common.truth.Truth.assertThat; import android.app.backup.FullBackup.BackupScheme.PathWithRequiredFlags; import android.content.Context; import android.platform.test.annotations.Presubmit; import com.android.server.testing.FrameworkRobolectricTestRunner; import com.android.server.testing.SystemLoaderPackages; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.annotation.internal.DoNotInstrument; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.stream.Collectors; import java.util.stream.Stream; @RunWith(FrameworkRobolectricTestRunner.class) @Config(manifest = Config.NONE, sdk = 26) @SystemLoaderPackages({"android.app.backup"}) @Presubmit @DoNotInstrument public class BackupUtilsTest { private Context mContext; @Before public void setUp() throws Exception { mContext = RuntimeEnvironment.application; } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListHasIt() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(file("a/b.txt"), paths(file("a/b.txt"))); assertThat(isSpecified).isTrue(); } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListHasItsDirectory() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(file("a/b.txt"), paths(directory("a"))); assertThat(isSpecified).isTrue(); } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListHasOtherFile() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(file("a/b.txt"), paths(file("a/c.txt"))); assertThat(isSpecified).isFalse(); } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListEmpty() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(file("a/b.txt"), paths()); assertThat(isSpecified).isFalse(); } @Test public void testIsFileSpecifiedInPathList_whenDirectoryAndPathListHasIt() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(directory("a"), paths(directory("a"))); assertThat(isSpecified).isTrue(); } @Test public void testIsFileSpecifiedInPathList_whenDirectoryAndPathListEmpty() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(directory("a"), paths()); assertThat(isSpecified).isFalse(); } @Test public void testIsFileSpecifiedInPathList_whenDirectoryAndPathListHasParent() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(directory("a/b"), paths(directory("a"))); assertThat(isSpecified).isFalse(); } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListDoesntContainDirectory() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(file("a/b.txt"), paths(directory("c"))); assertThat(isSpecified).isFalse(); } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListHasDirectoryWhoseNameIsPrefix() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList(file("a/b.txt"), paths(directory("a/b"))); assertThat(isSpecified).isFalse(); } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListHasDirectoryWhoseNameIsPrefix2() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList( file("name/subname.txt"), paths(directory("nam"))); assertThat(isSpecified).isFalse(); } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListContainsFirstNotRelatedAndSecondContainingDirectory() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList( file("a/b.txt"), paths(directory("b"), directory("a"))); assertThat(isSpecified).isTrue(); } @Test public void testIsFileSpecifiedInPathList_whenDirectoryAndPathListContainsFirstNotRelatedAndSecondSameDirectory() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList( directory("a/b"), paths(directory("b"), directory("a/b"))); assertThat(isSpecified).isTrue(); } @Test public void testIsFileSpecifiedInPathList_whenFileAndPathListContainsFirstNotRelatedFileAndSecondSameFile() throws Exception { boolean isSpecified = BackupUtils.isFileSpecifiedInPathList( file("a/b.txt"), paths(directory("b"), file("a/b.txt"))); assertThat(isSpecified).isTrue(); } private File file(String path) throws IOException { File file = new File(mContext.getDataDir(), path); File parent = file.getParentFile(); parent.mkdirs(); file.createNewFile(); if (!file.isFile()) { throw new IOException("Couldn't create file"); } return file; } private File directory(String path) throws IOException { File directory = new File(mContext.getDataDir(), path); directory.mkdirs(); if (!directory.isDirectory()) { throw new IOException("Couldn't create directory"); } return directory; } private Collection<PathWithRequiredFlags> paths(File... files) { return Stream.of(files) .map(file -> new PathWithRequiredFlags(file.getPath(), 0)) .collect(Collectors.toList()); } }