PinnerService.java revision 7bd0fdd639640f9ddffbffa6a117644134d8be30
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; 18 19import android.content.Context; 20import android.content.pm.PackageManager; 21import android.content.res.Resources; 22import android.util.EventLog; 23import android.util.Slog; 24import android.os.Binder; 25import android.os.Build; 26import android.system.ErrnoException; 27import android.system.Os; 28import android.system.OsConstants; 29import android.system.StructStat; 30 31import java.util.ArrayList; 32import java.io.FileDescriptor; 33import java.io.FileOutputStream; 34import java.io.IOException; 35import java.io.PrintWriter; 36 37/** 38 * <p>PinnerService pins important files for key processes in memory.</p> 39 * <p>Files to pin are specified in the config_defaultPinnerServiceFiles 40 * overlay. </p> 41 */ 42public final class PinnerService extends SystemService { 43 private static final boolean DEBUG = false; 44 private static final String TAG = "PinnerService"; 45 46 private final Context mContext; 47 private final ArrayList<String> mPinnedFiles = new ArrayList<String>(); 48 49 private BinderService mBinderService; 50 51 52 public PinnerService(Context context) { 53 super(context); 54 55 mContext = context; 56 57 } 58 59 @Override 60 public void onStart() { 61 Slog.e(TAG, "Starting PinnerService"); 62 63 mBinderService = new BinderService(); 64 publishBinderService("pinner", mBinderService); 65 66 // Files to pin come from the overlay and can be specified per-device config 67 // Continue trying to pin remaining files even if there is a failure 68 String[] filesToPin = mContext.getResources().getStringArray(com.android.internal.R.array.config_defaultPinnerServiceFiles); 69 for (int i = 0; i < filesToPin.length; i++){ 70 boolean success = pinFile(filesToPin[i], 0, 0); 71 if (success == true) { 72 mPinnedFiles.add(filesToPin[i]); 73 Slog.i(TAG, "Pinned file = " + filesToPin[i]); 74 } else { 75 Slog.e(TAG, "Failed to pin file = " + filesToPin[i]); 76 } 77 } 78 } 79 80 // mlock length bytes of fileToPin in memory, starting at offset 81 // length == 0 means pin from offset to end of file 82 private boolean pinFile(String fileToPin, long offset, long length) { 83 FileDescriptor fd = new FileDescriptor(); 84 try { 85 fd = Os.open(fileToPin, OsConstants.O_RDONLY | OsConstants.O_CLOEXEC | OsConstants.O_NOFOLLOW, OsConstants.O_RDONLY); 86 87 StructStat sb = Os.fstat(fd); 88 89 if (offset + length > sb.st_size) { 90 Os.close(fd); 91 return false; 92 } 93 94 if (length == 0) { 95 length = sb.st_size - offset; 96 } 97 98 long address = Os.mmap(0, length, OsConstants.PROT_READ, OsConstants.MAP_PRIVATE, fd, offset); 99 Os.close(fd); 100 101 Os.mlock(address, length); 102 103 return true; 104 } catch (ErrnoException e) { 105 Slog.e(TAG, "Failed to pin file " + fileToPin + " with error " + e.getMessage()); 106 if(fd.valid()) { 107 try { Os.close(fd); } 108 catch (ErrnoException eClose) {Slog.e(TAG, "Failed to close fd, error = " + eClose.getMessage());} 109 } 110 return false; 111 } 112 } 113 114 115 private final class BinderService extends Binder { 116 @Override 117 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 118 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 119 pw.println("Pinned Files:"); 120 for (int i = 0; i < mPinnedFiles.size(); i++) { 121 pw.println(mPinnedFiles.get(i)); 122 } 123 } 124 } 125} 126