blob: 46720152761db859ea01ec8dc4b38e92a29a84da [file] [log] [blame]
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -07001/*
2 * Copyright (C) 2014 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 android.content.pm;
18
19import android.app.PackageInstallObserver;
20import android.app.PackageUninstallObserver;
21import android.content.pm.PackageManager.NameNotFoundException;
Jeff Sharkey78cc3402014-05-22 10:52:49 -070022import android.os.FileBridge;
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070023import android.os.ParcelFileDescriptor;
24import android.os.RemoteException;
25
Jeff Sharkey78cc3402014-05-22 10:52:49 -070026import java.io.OutputStream;
27
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -070028/** {@hide} */
29public class PackageInstaller {
30 private final PackageManager mPm;
31 private final IPackageInstaller mInstaller;
32 private final int mUserId;
33 private final String mInstallerPackageName;
34
35 /** {@hide} */
36 public PackageInstaller(PackageManager pm, IPackageInstaller installer, int userId,
37 String installerPackageName) {
38 mPm = pm;
39 mInstaller = installer;
40 mUserId = userId;
41 mInstallerPackageName = installerPackageName;
42 }
43
44 public boolean isPackageAvailable(String basePackageName) {
45 try {
46 final ApplicationInfo info = mPm.getApplicationInfo(basePackageName,
47 PackageManager.GET_UNINSTALLED_PACKAGES);
48 return ((info.flags & ApplicationInfo.FLAG_INSTALLED) != 0);
49 } catch (NameNotFoundException e) {
50 return false;
51 }
52 }
53
54 public void installAvailablePackage(String basePackageName, PackageInstallObserver observer) {
55 int returnCode;
56 try {
57 returnCode = mPm.installExistingPackage(basePackageName);
58 } catch (NameNotFoundException e) {
59 returnCode = PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
60 }
61 observer.packageInstalled(basePackageName, null, returnCode);
62 }
63
64 public int createSession(PackageInstallerParams params) {
65 try {
66 return mInstaller.createSession(mUserId, mInstallerPackageName, params);
67 } catch (RemoteException e) {
68 throw e.rethrowAsRuntimeException();
69 }
70 }
71
72 public Session openSession(int sessionId) {
73 try {
74 return new Session(mInstaller.openSession(sessionId));
75 } catch (RemoteException e) {
76 throw e.rethrowAsRuntimeException();
77 }
78 }
79
80 public int[] getSessions() {
81 try {
82 return mInstaller.getSessions(mUserId, mInstallerPackageName);
83 } catch (RemoteException e) {
84 throw e.rethrowAsRuntimeException();
85 }
86 }
87
88 public void uninstall(String basePackageName, PackageUninstallObserver observer) {
89 try {
90 mInstaller.uninstall(mUserId, basePackageName, observer.getBinder());
91 } catch (RemoteException e) {
92 throw e.rethrowAsRuntimeException();
93 }
94 }
95
96 public void uninstall(String basePackageName, String splitName,
97 PackageUninstallObserver observer) {
98 try {
99 mInstaller.uninstallSplit(mUserId, basePackageName, splitName, observer.getBinder());
100 } catch (RemoteException e) {
101 throw e.rethrowAsRuntimeException();
102 }
103 }
104
105 /**
106 * An installation that is being actively staged. For an install to succeed,
107 * all existing and new packages must have identical package names, version
108 * codes, and signing certificates.
109 * <p>
110 * A session may contain any number of split packages. If the application
111 * does not yet exist, this session must include a base package.
112 * <p>
113 * If a package included in this session is already defined by the existing
114 * installation (for example, the same split name), the package in this
115 * session will replace the existing package.
116 */
117 public class Session {
118 private IPackageInstallerSession mSession;
119
120 /** {@hide} */
121 public Session(IPackageInstallerSession session) {
122 mSession = session;
123 }
124
125 public void updateProgress(int progress) {
126 try {
127 mSession.updateProgress(progress);
128 } catch (RemoteException e) {
129 throw e.rethrowAsRuntimeException();
130 }
131 }
132
Jeff Sharkey78cc3402014-05-22 10:52:49 -0700133 /**
134 * Open an APK file for writing, starting at the given offset. You can
135 * then stream data into the file, periodically calling
136 * {@link OutputStream#flush()} to ensure bytes have been written to
137 * disk.
138 */
139 public OutputStream openWrite(String splitName, long offsetBytes, long lengthBytes) {
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700140 try {
Jeff Sharkey78cc3402014-05-22 10:52:49 -0700141 final ParcelFileDescriptor clientSocket = mSession.openWrite(splitName,
142 offsetBytes, lengthBytes);
143 return new FileBridge.FileBridgeOutputStream(clientSocket.getFileDescriptor());
Jeff Sharkey3a44f3f2014-04-28 17:36:31 -0700144 } catch (RemoteException e) {
145 throw e.rethrowAsRuntimeException();
146 }
147 }
148
149 public void install(PackageInstallObserver observer) {
150 try {
151 mSession.install(observer.getBinder());
152 } catch (RemoteException e) {
153 throw e.rethrowAsRuntimeException();
154 }
155 }
156
157 public void close() {
158 // No resources to release at the moment
159 }
160
161 public void destroy() {
162 try {
163 mSession.destroy();
164 } catch (RemoteException e) {
165 throw e.rethrowAsRuntimeException();
166 }
167 }
168 }
169}