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