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