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