blob: c60460fccb76cf19c553b0234655bf38cc67bd36 [file] [log] [blame]
Howard Chenf17f42b2019-01-07 14:10:44 +08001/*
2 * Copyright (C) 2019 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.gsi.GsiProgress;
22import android.gsi.IGsiService;
David Anderson64143212019-07-12 16:24:09 -070023import android.gsi.IGsid;
Howard Chen148d7ed2019-03-26 16:13:04 +080024import android.os.Environment;
Howard Chenf17f42b2019-01-07 14:10:44 +080025import android.os.IBinder;
26import android.os.IBinder.DeathRecipient;
Howard Chenae615b32019-08-05 16:56:12 +080027import android.os.ParcelFileDescriptor;
Howard Chenf17f42b2019-01-07 14:10:44 +080028import android.os.RemoteException;
29import android.os.ServiceManager;
Howard Chen1392c142019-03-05 14:23:47 +080030import android.os.SystemProperties;
Howard Chen148d7ed2019-03-26 16:13:04 +080031import android.os.UserHandle;
Po-Chien Hsueh4e908c22019-03-07 11:57:17 +080032import android.os.image.IDynamicSystemService;
Howard Chen148d7ed2019-03-26 16:13:04 +080033import android.os.storage.StorageManager;
34import android.os.storage.StorageVolume;
Howard Chenf17f42b2019-01-07 14:10:44 +080035import android.util.Slog;
36
Howard Chen148d7ed2019-03-26 16:13:04 +080037import java.io.File;
38
Howard Chenf17f42b2019-01-07 14:10:44 +080039/**
Po-Chien Hsueh4e908c22019-03-07 11:57:17 +080040 * DynamicSystemService implements IDynamicSystemService. It provides permission check before
Howard Chenf17f42b2019-01-07 14:10:44 +080041 * passing requests to gsid
42 */
Po-Chien Hsueh4e908c22019-03-07 11:57:17 +080043public class DynamicSystemService extends IDynamicSystemService.Stub implements DeathRecipient {
44 private static final String TAG = "DynamicSystemService";
Howard Chenf17f42b2019-01-07 14:10:44 +080045 private static final String NO_SERVICE_ERROR = "no gsiservice";
Howard Chen1392c142019-03-05 14:23:47 +080046 private static final int GSID_ROUGH_TIMEOUT_MS = 8192;
Howard Chenc6f64c42019-11-10 01:11:50 +080047 private static final String PATH_DEFAULT = "/data/gsi/";
Howard Chenf17f42b2019-01-07 14:10:44 +080048 private Context mContext;
Howard Chenc6f64c42019-11-10 01:11:50 +080049 private String mInstallPath, mDsuSlot;
Howard Chenf17f42b2019-01-07 14:10:44 +080050 private volatile IGsiService mGsiService;
51
Po-Chien Hsueh4e908c22019-03-07 11:57:17 +080052 DynamicSystemService(Context context) {
Howard Chenf17f42b2019-01-07 14:10:44 +080053 mContext = context;
54 }
55
56 private static IGsiService connect(DeathRecipient recipient) throws RemoteException {
57 IBinder binder = ServiceManager.getService("gsiservice");
58 if (binder == null) {
Po-Chien Hsueh7565fcc2019-04-11 16:36:54 +080059 return null;
Howard Chenf17f42b2019-01-07 14:10:44 +080060 }
61 /**
62 * The init will restart gsiservice if it crashed and the proxy object will need to be
63 * re-initialized in this case.
64 */
65 binder.linkToDeath(recipient, 0);
David Anderson64143212019-07-12 16:24:09 -070066
67 IGsid gsid = IGsid.Stub.asInterface(binder);
68 return gsid.getClient();
Howard Chenf17f42b2019-01-07 14:10:44 +080069 }
70
71 /** implements DeathRecipient */
72 @Override
73 public void binderDied() {
74 Slog.w(TAG, "gsiservice died; reconnecting");
75 synchronized (this) {
76 mGsiService = null;
77 }
78 }
79
80 private IGsiService getGsiService() throws RemoteException {
81 checkPermission();
Po-Chien Hsueh7565fcc2019-04-11 16:36:54 +080082
Howard Chen1392c142019-03-05 14:23:47 +080083 if (!"running".equals(SystemProperties.get("init.svc.gsid"))) {
84 SystemProperties.set("ctl.start", "gsid");
Po-Chien Hsueh7565fcc2019-04-11 16:36:54 +080085 }
86
87 for (int sleepMs = 64; sleepMs <= (GSID_ROUGH_TIMEOUT_MS << 1); sleepMs <<= 1) {
88 synchronized (this) {
89 if (mGsiService == null) {
90 mGsiService = connect(this);
Howard Chen72324e42019-03-29 16:38:39 +080091 }
Po-Chien Hsueh7565fcc2019-04-11 16:36:54 +080092 if (mGsiService != null) {
93 return mGsiService;
Howard Chen1392c142019-03-05 14:23:47 +080094 }
95 }
Po-Chien Hsueh7565fcc2019-04-11 16:36:54 +080096
97 try {
98 Slog.d(TAG, "GsiService is not ready, wait for " + sleepMs + "ms");
99 Thread.sleep(sleepMs);
100 } catch (InterruptedException e) {
101 Slog.e(TAG, "Interrupted when waiting for GSID");
102 return null;
Howard Chen72324e42019-03-29 16:38:39 +0800103 }
Howard Chen72324e42019-03-29 16:38:39 +0800104 }
Po-Chien Hsueh7565fcc2019-04-11 16:36:54 +0800105
106 throw new RemoteException(NO_SERVICE_ERROR);
Howard Chenf17f42b2019-01-07 14:10:44 +0800107 }
108
109 private void checkPermission() {
110 if (mContext.checkCallingOrSelfPermission(
Po-Chien Hsueh4e908c22019-03-07 11:57:17 +0800111 android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
Howard Chenf17f42b2019-01-07 14:10:44 +0800112 != PackageManager.PERMISSION_GRANTED) {
Po-Chien Hsueh4e908c22019-03-07 11:57:17 +0800113 throw new SecurityException("Requires MANAGE_DYNAMIC_SYSTEM permission");
Howard Chenf17f42b2019-01-07 14:10:44 +0800114 }
115 }
116
117 @Override
Howard Chenc6f64c42019-11-10 01:11:50 +0800118 public boolean startInstallation(String dsuSlot) throws RemoteException {
Howard Chen6ea5bed2019-10-04 18:15:14 +0800119 IGsiService service = getGsiService();
Howard Chen148d7ed2019-03-26 16:13:04 +0800120 // priority from high to low: sysprop -> sdcard -> /data
121 String path = SystemProperties.get("os.aot.path");
122 if (path.isEmpty()) {
123 final int userId = UserHandle.myUserId();
124 final StorageVolume[] volumes =
125 StorageManager.getVolumeList(userId, StorageManager.FLAG_FOR_WRITE);
126 for (StorageVolume volume : volumes) {
127 if (volume.isEmulated()) continue;
128 if (!volume.isRemovable()) continue;
129 if (!Environment.MEDIA_MOUNTED.equals(volume.getState())) continue;
130 File sdCard = volume.getPathFile();
131 if (sdCard.isDirectory()) {
Howard Chenc6f64c42019-11-10 01:11:50 +0800132 path = new File(sdCard, dsuSlot).getPath();
Howard Chen148d7ed2019-03-26 16:13:04 +0800133 break;
134 }
135 }
136 if (path.isEmpty()) {
Howard Chenc6f64c42019-11-10 01:11:50 +0800137 path = PATH_DEFAULT + dsuSlot;
Howard Chen148d7ed2019-03-26 16:13:04 +0800138 }
139 Slog.i(TAG, "startInstallation -> " + path);
140 }
Howard Chen6ea5bed2019-10-04 18:15:14 +0800141 mInstallPath = path;
Howard Chenc6f64c42019-11-10 01:11:50 +0800142 mDsuSlot = dsuSlot;
Howard Chen6ea5bed2019-10-04 18:15:14 +0800143 if (service.openInstall(path) != 0) {
144 Slog.i(TAG, "Failed to open " + path);
145 return false;
146 }
147 return true;
148 }
149
150 @Override
151 public boolean createPartition(String name, long size, boolean readOnly)
152 throws RemoteException {
Howard Chene176c562019-08-13 17:01:53 +0800153 IGsiService service = getGsiService();
Howard Chen6ea5bed2019-10-04 18:15:14 +0800154 if (service.createPartition(name, size, readOnly) != 0) {
Howard Chene176c562019-08-13 17:01:53 +0800155 Slog.i(TAG, "Failed to install " + name);
156 return false;
157 }
158 return true;
Howard Chenf17f42b2019-01-07 14:10:44 +0800159 }
160
161 @Override
Howard Chen6ea5bed2019-10-04 18:15:14 +0800162 public boolean finishInstallation() throws RemoteException {
163 IGsiService service = getGsiService();
164 if (service.closeInstall() != 0) {
165 Slog.i(TAG, "Failed to finish installation");
166 return false;
167 }
168 return true;
169 }
170
171 @Override
Howard Chenf17f42b2019-01-07 14:10:44 +0800172 public GsiProgress getInstallationProgress() throws RemoteException {
173 return getGsiService().getInstallProgress();
174 }
175
176 @Override
177 public boolean abort() throws RemoteException {
178 return getGsiService().cancelGsiInstall();
179 }
180
181 @Override
182 public boolean isInUse() throws RemoteException {
Howard Chen07fcb2f2019-12-19 11:40:16 +0800183 return SystemProperties.getBoolean("ro.gsid.image_running", false);
Howard Chenf17f42b2019-01-07 14:10:44 +0800184 }
185
186 @Override
187 public boolean isInstalled() throws RemoteException {
188 return getGsiService().isGsiInstalled();
189 }
190
191 @Override
Howard Chen72324e42019-03-29 16:38:39 +0800192 public boolean isEnabled() throws RemoteException {
193 return getGsiService().isGsiEnabled();
194 }
195
196 @Override
Howard Chenf17f42b2019-01-07 14:10:44 +0800197 public boolean remove() throws RemoteException {
Howard Chen6ea5bed2019-10-04 18:15:14 +0800198 IGsiService gsiService = getGsiService();
199 String install_dir = gsiService.getInstalledGsiImageDir();
Howard Chenc44ee152019-08-02 17:54:49 +0800200 return getGsiService().removeGsi();
Howard Chenf17f42b2019-01-07 14:10:44 +0800201 }
202
203 @Override
Howard Chenc44ee152019-08-02 17:54:49 +0800204 public boolean setEnable(boolean enable, boolean oneShot) throws RemoteException {
Howard Chenf17f42b2019-01-07 14:10:44 +0800205 IGsiService gsiService = getGsiService();
Howard Chen72324e42019-03-29 16:38:39 +0800206 if (enable) {
Howard Chenc6f64c42019-11-10 01:11:50 +0800207 return gsiService.enableGsi(oneShot, mDsuSlot) == 0;
Howard Chen72324e42019-03-29 16:38:39 +0800208 } else {
Howard Chenc44ee152019-08-02 17:54:49 +0800209 return gsiService.disableGsi();
Howard Chenf17f42b2019-01-07 14:10:44 +0800210 }
211 }
212
213 @Override
Howard Chenae615b32019-08-05 16:56:12 +0800214 public boolean setAshmem(ParcelFileDescriptor ashmem, long size) {
215 try {
216 return getGsiService().setGsiAshmem(ashmem, size);
217 } catch (RemoteException e) {
218 throw new RuntimeException(e.toString());
219 }
220 }
221
222 @Override
223 public boolean submitFromAshmem(long size) {
224 try {
225 return getGsiService().commitGsiChunkFromAshmem(size);
226 } catch (RemoteException e) {
227 throw new RuntimeException(e.toString());
228 }
Howard Chenf17f42b2019-01-07 14:10:44 +0800229 }
Howard Chenf17f42b2019-01-07 14:10:44 +0800230}