summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java125
-rw-r--r--services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java10
2 files changed, 135 insertions, 0 deletions
diff --git a/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java b/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
new file mode 100644
index 000000000000..848017063bff
--- /dev/null
+++ b/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.retaildemo;
+
+import android.app.AppGlobals;
+import android.app.PackageInstallObserver;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Helper class for installing preloaded APKs
+ */
+class PreloadAppsInstaller {
+ private static final String SYSTEM_SERVER_PACKAGE_NAME = "android";
+ private static String TAG = PreloadAppsInstaller.class.getSimpleName();
+ private static final String PRELOAD_APK_EXT = ".apk.preload";
+ private static boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private final IPackageManager mPackageManager;
+ private final File preloadsAppsDirectory;
+
+ private final Map<String, String> mApkToPackageMap;
+
+ PreloadAppsInstaller() {
+ this(AppGlobals.getPackageManager(), Environment.getDataPreloadsAppsDirectory());
+ }
+
+ @VisibleForTesting
+ PreloadAppsInstaller(IPackageManager packageManager, File preloadsAppsDirectory) {
+ mPackageManager = packageManager;
+ mApkToPackageMap = Collections.synchronizedMap(new ArrayMap<>());
+ this.preloadsAppsDirectory = preloadsAppsDirectory;
+ }
+
+ void installApps(int userId) {
+ File[] files = preloadsAppsDirectory.listFiles();
+ if (ArrayUtils.isEmpty(files)) {
+ return;
+ }
+ for (File file : files) {
+ String apkName = file.getName();
+ if (apkName.endsWith(PRELOAD_APK_EXT) && file.isFile()) {
+ String packageName = mApkToPackageMap.get(apkName);
+ if (packageName != null) {
+ try {
+ installExistingPackage(packageName, userId);
+ } catch (Exception e) {
+ Slog.e(TAG, "Failed to install existing package " + packageName, e);
+ }
+ } else {
+ try {
+ installPackage(file, userId);
+ } catch (Exception e) {
+ Slog.e(TAG, "Failed to install package from " + file, e);
+ }
+ }
+ }
+ }
+ }
+
+ private void installExistingPackage(String packageName, int userId) {
+ if (DEBUG) {
+ Log.d(TAG, "installExistingPackage " + packageName + " u" + userId);
+ }
+ try {
+ mPackageManager.installExistingPackageAsUser(packageName, userId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ private void installPackage(File file, final int userId) throws IOException, RemoteException {
+ final String apkName = file.getName();
+ if (DEBUG) {
+ Log.d(TAG, "installPackage " + apkName + " u" + userId);
+ }
+ mPackageManager.installPackageAsUser(file.getPath(), new PackageInstallObserver() {
+ @Override
+ public void onPackageInstalled(String basePackageName, int returnCode, String msg,
+ Bundle extras) {
+ if (DEBUG) {
+ Log.d(TAG, "Package " + basePackageName + " installed u" + userId
+ + " returnCode: " + returnCode + " msg: " + msg);
+ }
+ if (returnCode == PackageManager.INSTALL_SUCCEEDED) {
+ mApkToPackageMap.put(apkName, basePackageName);
+ // Install on user 0 so that the package is cached when demo user is re-created
+ installExistingPackage(basePackageName, UserHandle.USER_SYSTEM);
+ } else if (returnCode == PackageManager.INSTALL_FAILED_ALREADY_EXISTS) {
+ installExistingPackage(basePackageName, userId);
+ }
+ }
+ }.getBinder(), 0, SYSTEM_SERVER_PACKAGE_NAME, userId);
+ }
+
+} \ No newline at end of file
diff --git a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
index 2529564107b2..04049a17e6ce 100644
--- a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
@@ -110,6 +110,7 @@ public class RetailDemoModeService extends SystemService {
private CameraManager mCameraManager;
private String[] mCameraIdsWithFlash;
private Configuration mSystemUserConfiguration;
+ private PreloadAppsInstaller mPreloadAppsInstaller;
final Object mActivityLock = new Object();
// Whether the newly created demo user has interacted with the screen yet
@@ -203,6 +204,7 @@ public class RetailDemoModeService extends SystemService {
synchronized (mActivityLock) {
mFirstUserActivityTime = mLastUserActivityTime = SystemClock.uptimeMillis();
}
+ mPreloadAppsInstaller = new PreloadAppsInstaller();
}
private Notification createResetNotification() {
@@ -253,6 +255,8 @@ public class RetailDemoModeService extends SystemService {
um.setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user);
Settings.Secure.putIntForUser(getContext().getContentResolver(),
Settings.Secure.SKIP_FIRST_USE_HINTS, 1, userInfo.id);
+ Settings.Secure.putIntForUser(getContext().getContentResolver(),
+ Settings.Global.PACKAGE_VERIFIER_ENABLE, 0, userInfo.id);
grantRuntimePermissionToCamera(userInfo.getUserHandle());
}
@@ -458,6 +462,12 @@ public class RetailDemoModeService extends SystemService {
}
MetricsLogger.count(getContext(), DEMO_SESSION_COUNT, 1);
mHandler.removeMessages(MSG_INACTIVITY_TIME_OUT);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mPreloadAppsInstaller.installApps(userId);
+ }
+ });
}
private RetailDemoModeServiceInternal mLocalService = new RetailDemoModeServiceInternal() {