Home | History | Annotate | Download | only in tasks
      1 #!/usr/bin/env python3
      2 #
      3 # Copyright (C) 2019 The Android Open Source Project
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the "License");
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #      http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an "AS IS" BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 #
     17 import os
     18 import subprocess
     19 from glob import glob
     20 from collections import defaultdict
     21 import sys
     22 import json
     23 
     24 if len(sys.argv) < 3:
     25     product_out = os.environ["PRODUCT_OUT"]
     26     aapt = "aapt2"
     27 else:
     28     product_out = sys.argv[1]
     29     aapt = sys.argv[2]
     30 
     31 def execute(cmd):
     32     p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     33     out, err = map(lambda b: b.decode('utf-8'), p.communicate())
     34     return p.returncode == 0, out, err
     35 
     36 def make_aapt_cmds(file):
     37     return [aapt + ' dump ' + file + ' --file AndroidManifest.xml',
     38             aapt + ' dump xmltree ' + file + ' --file AndroidManifest.xml']
     39 
     40 def extract_shared_uid(file):
     41     for cmd in make_aapt_cmds(file):
     42         success, manifest, error_msg = execute(cmd)
     43         if success:
     44             break
     45     else:
     46         print(error_msg, file=sys.stderr)
     47         sys.exit()
     48         return None
     49 
     50     for l in manifest.split('\n'):
     51         if "sharedUserId" in l:
     52             return l.split('"')[-2]
     53     return None
     54 
     55 
     56 partitions = ["system", "vendor", "product"]
     57 
     58 shareduid_app_dict = defaultdict(list)
     59 
     60 for p in partitions:
     61     for f in glob(os.path.join(product_out, p, "*", "*", "*.apk")):
     62         apk_file = os.path.basename(f)
     63         shared_uid = extract_shared_uid(f)
     64 
     65         if shared_uid is None:
     66             continue
     67         shareduid_app_dict[shared_uid].append((p, apk_file))
     68 
     69 
     70 output = defaultdict(lambda: defaultdict(list))
     71 
     72 for uid, app_infos in shareduid_app_dict.items():
     73     partitions = {p for p, _ in app_infos}
     74     if len(partitions) > 1:
     75         for part in partitions:
     76             output[uid][part].extend([a for p, a in app_infos if p == part])
     77 
     78 print(json.dumps(output, indent=2, sort_keys=True))
     79