Merge changes I6f19b810,I0fd91e2a am: 83e62acb23

Original change: https://android-review.googlesource.com/c/platform/packages/modules/SdkExtensions/+/2060061

Change-Id: Id6a3d7a8325ab9b13fc988476e66bd0013a37efe
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/gen_sdk/gen_sdk.py b/gen_sdk/gen_sdk.py
index 3353fd4..44cf197 100644
--- a/gen_sdk/gen_sdk.py
+++ b/gen_sdk/gen_sdk.py
@@ -62,7 +62,8 @@
   parser.add_argument(
     '--modules',
     metavar='MODULES',
-    help='Comma-separated list of modules providing new APIs. Required for action=new_sdk.'
+    help='Comma-separated list of modules providing new APIs. Used for action=new_sdk to create a '
+         'new SDK that only requires new versions of some modules.'
   )
   return parser.parse_args(argv)
 
@@ -99,6 +100,14 @@
           if prev.version > requirement.version.version:
             return 'Found module requirement moving backwards: %s in %s' % (requirement, version)
         prev_requirements[requirement.module] = requirement.version
+
+    for version in database.versions:
+      required_modules = [r.module for r in version.requirements]
+      if SdkModule.UNKNOWN in required_modules:
+        return 'SDK %d has a requirement on the UNKNOWN module' % version.version
+      if not all([m in SdkModule.values() for m in required_modules]):
+        return 'SDK %d has a requirement on an undefined module value' % version.version
+
     return None
 
   err = find_bug()
@@ -107,7 +116,19 @@
     sys.exit(1)
 
 
-def NewSdk(database, new_version, modules):
+def NewSdk(database, args):
+  if not args.sdk:
+    print('Missing required argument --sdk for action new_sdk')
+    sys.exit(1)
+
+  new_version = args.sdk
+  if args.modules:
+    module_names = args.modules.split(',')
+  else:
+    # Default: require all modules
+    module_names = [m for m in SdkModule.keys() if not m == 'UNKNOWN']
+
+  module_values = [SdkModule.Value(m) for m in module_names]
   new_requirements = {}
 
   # Gather the previous highest requirement of each module
@@ -116,7 +137,7 @@
       new_requirements[prev_requirement.module] = prev_requirement.version
 
   # Add new requirements of this version
-  for module in modules:
+  for module in module_values:
     new_requirements[module] = SdkVersion(version=new_version)
 
   to_proto = lambda m : ExtensionVersion.ModuleRequirement(module=m, version=new_requirements[m])
@@ -124,8 +145,7 @@
   extension_version = ExtensionVersion(version=new_version, requirements=module_requirements)
   database.versions.append(extension_version)
 
-  module_names = ','.join([SdkModule.Name(m) for m in modules])
-  print('Created a new extension SDK level %d with modules %s' % (new_version, module_names))
+  print('Created a new extension SDK level %d with modules %s' % (new_version, ','.join(module_names)))
 
 
 def main(argv):
@@ -133,15 +153,12 @@
   with args.database.open('r') as f:
     database = google.protobuf.text_format.Parse(f.read(), ExtensionDatabase())
 
-  if args.modules:
-    modules = [SdkModule.Value(m) for m in args.modules.split(',')]
-
   ValidateDatabase(database, 'Input database')
 
   {
     'validate': lambda : print('Validated database'),
     'print_binary': lambda : PrintBinary(database),
-    'new_sdk': lambda : NewSdk(database, args.sdk, modules)
+    'new_sdk': lambda : NewSdk(database, args)
   }[args.action]()
 
   if args.action in ['new_sdk']:
diff --git a/gen_sdk/gen_sdk_test.sh b/gen_sdk/gen_sdk_test.sh
index a0b9b7b..15aa524 100644
--- a/gen_sdk/gen_sdk_test.sh
+++ b/gen_sdk/gen_sdk_test.sh
@@ -36,7 +36,7 @@
 test_print_binary
 
 # Verifies the tool is able to re-create the test DB correctly.
-function test_new_sdk() {
+function test_new_sdk_filtered() {
   db=${tmp_dir}/extensions_db.textpb
   rm -f ${db} && touch ${db}
   gen_sdk --action new_sdk --sdk 1 --modules MEDIA_PROVIDER --database ${db}
@@ -46,7 +46,17 @@
 
   diff -u0 testdata/test_extensions_db.textpb ${db}
 }
-test_new_sdk
+test_new_sdk_filtered
+
+# Verifies the tool can create new SDKs requiring all modules
+function test_new_sdk_all_modules() {
+  db=${tmp_dir}/extensions_db.textpb
+  rm -f ${db} && touch ${db}
+  gen_sdk --action new_sdk --sdk 1 --database ${db} | grep -q MEDIA_PROVIDER
+  gen_sdk --action new_sdk --sdk 2 --database ${db} | grep -q ART
+  ! gen_sdk --action new_sdk --sdk 3 --database ${db} | grep -q UNKNOWN
+}
+test_new_sdk_all_modules
 
 # Verifies the tool won't allow bogus SDK updates
 function test_validate() {
@@ -77,6 +87,22 @@
     exit 1
   fi
 
+  if gen_sdk --action validate --database testdata/unknown_module.textpb; then
+    echo "FAILED: expect sdk containing UNKNOWN module to be invalid"
+    exit 1
+  fi
+
+  if gen_sdk --action validate --database testdata/undefined_module.textpb; then
+    echo "FAILED: expect sdk containing undefined module to be invalid"
+    exit 1
+  fi
+
+  rm -f ${db} && touch ${db}
+  if gen_sdk --action new_sdk --sdk 1 --modules UNKNOWN --database ${db}; then
+    echo "FAILED: expected new sdk with UNKNOWN module to be invalid"
+    exit 1
+  fi
+
   set -e
 }
 test_validate
diff --git a/gen_sdk/testdata/undefined_module.textpb b/gen_sdk/testdata/undefined_module.textpb
new file mode 100644
index 0000000..f350119
--- /dev/null
+++ b/gen_sdk/testdata/undefined_module.textpb
@@ -0,0 +1,15 @@
+versions {
+  version: 1
+  requirements {
+    module: SOMETHING_UNDEFINED
+    version {
+      version: 1
+    }
+  }
+  requirements {
+    module: MEDIA_PROVIDER
+    version {
+      version: 2
+    }
+  }
+}
diff --git a/gen_sdk/testdata/unknown_module.textpb b/gen_sdk/testdata/unknown_module.textpb
new file mode 100644
index 0000000..b30c79a
--- /dev/null
+++ b/gen_sdk/testdata/unknown_module.textpb
@@ -0,0 +1,15 @@
+versions {
+  version: 1
+  requirements {
+    module: UNKNOWN
+    version {
+      version: 1
+    }
+  }
+  requirements {
+    module: MEDIA_PROVIDER
+    version {
+      version: 2
+    }
+  }
+}