1eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad/* 2eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * Copyright (C) 2016 The Android Open Source Project 3eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * 4eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * Licensed under the Apache License, Version 2.0 (the "License"); 5eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * you may not use this file except in compliance with the License. 6eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * You may obtain a copy of the License at 7eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * 8eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * http://www.apache.org/licenses/LICENSE-2.0 9eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * 10eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * Unless required by applicable law or agreed to in writing, software 11eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * distributed under the License is distributed on an "AS IS" BASIS, 12eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * See the License for the specific language governing permissions and 14eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * limitations under the License. 15eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad */ 16eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad 17eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadpackage com.android.server.om; 18eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad 19eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport static com.android.server.om.OverlayManagerService.DEBUG; 20eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport static com.android.server.om.OverlayManagerService.TAG; 21eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad 22eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport android.annotation.NonNull; 23eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport android.content.om.OverlayInfo; 24eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport android.content.pm.PackageInfo; 25eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport android.os.UserHandle; 26eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport android.util.Slog; 27eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad 28eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport com.android.server.pm.Installer.InstallerException; 29eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport com.android.server.pm.Installer; 30eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad 31eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport java.io.DataInputStream; 32eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport java.io.File; 33eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport java.io.FileInputStream; 34eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadimport java.io.IOException; 35eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad 36eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad/** 37eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * Handle the creation and deletion of idmap files. 38eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * 39eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * The actual work is performed by the idmap binary, launched through Installer 40eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * and installd. 41eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * 42eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad * Note: this class is subclassed in the OMS unit tests, and hence not marked as final. 43eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad */ 44eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstadclass IdmapManager { 45eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad private final Installer mInstaller; 46eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad 47eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad IdmapManager(final Installer installer) { 48eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad mInstaller = installer; 49eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad } 50eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad 51eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad boolean createIdmap(@NonNull final PackageInfo targetPackage, 52eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad @NonNull final PackageInfo overlayPackage, int userId) { 53eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible 54eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad if (DEBUG) { 55eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad Slog.d(TAG, "create idmap for " + targetPackage.packageName + " and " 56eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad + overlayPackage.packageName); 57eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad } 58eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad final int sharedGid = UserHandle.getSharedAppGid(targetPackage.applicationInfo.uid); 59eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad final String targetPath = targetPackage.applicationInfo.getBaseCodePath(); 60eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad final String overlayPath = overlayPackage.applicationInfo.getBaseCodePath(); 61eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad try { 62eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad mInstaller.idmap(targetPath, overlayPath, sharedGid); 63eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad } catch (InstallerException e) { 64eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad Slog.w(TAG, "failed to generate idmap for " + targetPath + " and " 65eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad + overlayPath + ": " + e.getMessage()); 66eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad return false; 67eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad } 68eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad return true; 69eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad } 70eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad 71eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad boolean removeIdmap(@NonNull final OverlayInfo oi, final int userId) { 72eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible 73eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad if (DEBUG) { 74eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad Slog.d(TAG, "remove idmap for " + oi.baseCodePath); 75eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad } 76eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad try { 77eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad mInstaller.removeIdmap(oi.baseCodePath); 78eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad } catch (InstallerException e) { 79eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad Slog.w(TAG, "failed to remove idmap for " + oi.baseCodePath + ": " + e.getMessage()); 80eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad return false; 81eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad } 82eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad return true; 83eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad } 84eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad 85eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad boolean idmapExists(@NonNull final OverlayInfo oi) { 86eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad // unused OverlayInfo.userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible 87eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad return new File(getIdmapPath(oi.baseCodePath)).isFile(); 88eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad } 89eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad 90eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad boolean idmapExists(@NonNull final PackageInfo overlayPackage, final int userId) { 91eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible 92eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad return new File(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath())).isFile(); 93eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad } 94eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad 95eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad boolean isDangerous(@NonNull final PackageInfo overlayPackage, final int userId) { 96eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible 97eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad return isDangerous(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath())); 98eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad } 99eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad 100eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad private String getIdmapPath(@NonNull final String baseCodePath) { 101eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad final StringBuilder sb = new StringBuilder("/data/resource-cache/"); 102eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad sb.append(baseCodePath.substring(1).replace('/', '@')); 103eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad sb.append("@idmap"); 104eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad return sb.toString(); 105eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad } 106eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad 107eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad private boolean isDangerous(@NonNull final String idmapPath) { 108eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad try (DataInputStream dis = new DataInputStream(new FileInputStream(idmapPath))) { 109eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad final int magic = dis.readInt(); 110eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad final int version = dis.readInt(); 111eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad final int dangerous = dis.readInt(); 112eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad return dangerous != 0; 113eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad } catch (IOException e) { 114eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad return true; 115eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad } 116eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad } 117eabc9e95768e7ac9acc3b32dc9ac2edf99c9e2c5Mårten Kongstad} 118