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 Object mLock = new Object(); 49 50 /** 51 * Instance that maintains the socket connection to the zygote. This is {@code null} if the 52 * zygote is not running or is not connected. 53 */ 54 @GuardedBy("mLock") 55 private ChildZygoteProcess mZygote; 56 57 private final ApplicationInfo mAppInfo; 58 AppZygote(ApplicationInfo appInfo, int zygoteUid, int uidGidMin, int uidGidMax)59 public AppZygote(ApplicationInfo appInfo, int zygoteUid, int uidGidMin, int uidGidMax) { 60 mAppInfo = appInfo; 61 mZygoteUid = zygoteUid; 62 mZygoteUidGidMin = uidGidMin; 63 mZygoteUidGidMax = uidGidMax; 64 } 65 66 /** 67 * Returns the zygote process associated with this app zygote. 68 * Creates the process if it's not already running. 69 */ getProcess()70 public ChildZygoteProcess getProcess() { 71 synchronized (mLock) { 72 if (mZygote != null) return mZygote; 73 74 connectToZygoteIfNeededLocked(); 75 return mZygote; 76 } 77 } 78 79 /** 80 * Stops the Zygote and kills the zygote process. 81 */ stopZygote()82 public void stopZygote() { 83 synchronized (mLock) { 84 stopZygoteLocked(); 85 } 86 } 87 getAppInfo()88 public ApplicationInfo getAppInfo() { 89 return mAppInfo; 90 } 91 92 @GuardedBy("mLock") stopZygoteLocked()93 private void stopZygoteLocked() { 94 if (mZygote != null) { 95 mZygote.close(); 96 // use killProcessGroup() here, so we kill all untracked children as well. 97 Process.killProcessGroup(mZygoteUid, mZygote.getPid()); 98 mZygote = null; 99 } 100 } 101 102 @GuardedBy("mLock") connectToZygoteIfNeededLocked()103 private void connectToZygoteIfNeededLocked() { 104 String abi = mAppInfo.primaryCpuAbi != null ? mAppInfo.primaryCpuAbi : 105 Build.SUPPORTED_ABIS[0]; 106 try { 107 mZygote = Process.ZYGOTE_PROCESS.startChildZygote( 108 "com.android.internal.os.AppZygoteInit", 109 mAppInfo.processName + "_zygote", 110 mZygoteUid, 111 mZygoteUid, 112 null, // gids 113 0, // runtimeFlags 114 "app_zygote", // seInfo 115 abi, // abi 116 abi, // acceptedAbiList 117 VMRuntime.getInstructionSet(abi), // instructionSet 118 mZygoteUidGidMin, 119 mZygoteUidGidMax); 120 121 ZygoteProcess.waitForConnectionToZygote(mZygote.getPrimarySocketAddress()); 122 // preload application code in the zygote 123 Log.i(LOG_TAG, "Starting application preload."); 124 mZygote.preloadApp(mAppInfo, abi); 125 Log.i(LOG_TAG, "Application preload done."); 126 } catch (Exception e) { 127 Log.e(LOG_TAG, "Error connecting to app zygote", e); 128 stopZygoteLocked(); 129 } 130 } 131 } 132