1 /* 2 * Copyright (C) 2018 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 17 package android.os; 18 19 import android.content.pm.ApplicationInfo; 20 import android.content.pm.ProcessInfo; 21 import android.util.Log; 22 23 import com.android.internal.annotations.GuardedBy; 24 import com.android.internal.os.Zygote; 25 26 import dalvik.system.VMRuntime; 27 28 /** 29 * AppZygote is responsible for interfacing with an application-specific zygote. 30 * 31 * Application zygotes can pre-load app-specific code and data, and this interface can 32 * be used to spawn isolated services from such an application zygote. 33 * 34 * Note that we'll have only one instance of this per application / uid combination. 35 * 36 * @hide 37 */ 38 public class AppZygote { 39 private static final String LOG_TAG = "AppZygote"; 40 41 // UID of the Zygote itself 42 private final int mZygoteUid; 43 44 // First UID/GID of the range the AppZygote can setuid()/setgid() to 45 private final int mZygoteUidGidMin; 46 47 // Last UID/GID of the range the AppZygote can setuid()/setgid() to 48 private final int mZygoteUidGidMax; 49 50 private final Object mLock = new Object(); 51 52 /** 53 * Instance that maintains the socket connection to the zygote. This is {@code null} if the 54 * zygote is not running or is not connected. 55 */ 56 @GuardedBy("mLock") 57 private ChildZygoteProcess mZygote; 58 59 private final ApplicationInfo mAppInfo; 60 private final ProcessInfo mProcessInfo; 61 AppZygote(ApplicationInfo appInfo, ProcessInfo processInfo, int zygoteUid, int uidGidMin, int uidGidMax)62 public AppZygote(ApplicationInfo appInfo, ProcessInfo processInfo, int zygoteUid, int uidGidMin, 63 int uidGidMax) { 64 mAppInfo = appInfo; 65 mProcessInfo = processInfo; 66 mZygoteUid = zygoteUid; 67 mZygoteUidGidMin = uidGidMin; 68 mZygoteUidGidMax = uidGidMax; 69 } 70 71 /** 72 * Returns the zygote process associated with this app zygote. 73 * Creates the process if it's not already running. 74 */ getProcess()75 public ChildZygoteProcess getProcess() { 76 synchronized (mLock) { 77 if (mZygote != null) return mZygote; 78 79 connectToZygoteIfNeededLocked(); 80 return mZygote; 81 } 82 } 83 84 /** 85 * Stops the Zygote and kills the zygote process. 86 */ stopZygote()87 public void stopZygote() { 88 synchronized (mLock) { 89 stopZygoteLocked(); 90 } 91 } 92 getAppInfo()93 public ApplicationInfo getAppInfo() { 94 return mAppInfo; 95 } 96 97 @GuardedBy("mLock") stopZygoteLocked()98 private void stopZygoteLocked() { 99 if (mZygote != null) { 100 mZygote.close(); 101 // use killProcessGroup() here, so we kill all untracked children as well. 102 Process.killProcessGroup(mZygoteUid, mZygote.getPid()); 103 mZygote = null; 104 } 105 } 106 107 @GuardedBy("mLock") connectToZygoteIfNeededLocked()108 private void connectToZygoteIfNeededLocked() { 109 String abi = mAppInfo.primaryCpuAbi != null ? mAppInfo.primaryCpuAbi : 110 Build.SUPPORTED_ABIS[0]; 111 try { 112 int runtimeFlags = Zygote.getMemorySafetyRuntimeFlagsForSecondaryZygote( 113 mAppInfo, mProcessInfo); 114 mZygote = Process.ZYGOTE_PROCESS.startChildZygote( 115 "com.android.internal.os.AppZygoteInit", 116 mAppInfo.processName + "_zygote", 117 mZygoteUid, 118 mZygoteUid, 119 null, // gids 120 runtimeFlags, 121 "app_zygote", // seInfo 122 abi, // abi 123 abi, // acceptedAbiList 124 VMRuntime.getInstructionSet(abi), // instructionSet 125 mZygoteUidGidMin, 126 mZygoteUidGidMax); 127 128 ZygoteProcess.waitForConnectionToZygote(mZygote.getPrimarySocketAddress()); 129 // preload application code in the zygote 130 Log.i(LOG_TAG, "Starting application preload."); 131 mZygote.preloadApp(mAppInfo, abi); 132 Log.i(LOG_TAG, "Application preload done."); 133 } catch (Exception e) { 134 Log.e(LOG_TAG, "Error connecting to app zygote", e); 135 stopZygoteLocked(); 136 } 137 } 138 } 139