Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 85acc4ba authored by Ivan Chiang's avatar Ivan Chiang Committed by Android (Google) Code Review
Browse files

Revert^2 "[PM] Remove wear folder and the usage of xz-java"

This reverts commit 307ebea4.

Reason for revert: The issue in wear settings was fixed. Re-land this patch.

Change-Id: I88a699db2749fb5637953364f305787f5aa13851
parent 307ebea4
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -46,7 +46,6 @@ android_app {
    sdk_version: "system_current",
    rename_resources_package: false,
    static_libs: [
        "xz-java",
        "androidx.leanback_leanback",
        "androidx.annotation_annotation",
        "androidx.fragment_fragment",
@@ -79,7 +78,6 @@ android_app {
    overrides: ["PackageInstaller"],

    static_libs: [
        "xz-java",
        "androidx.leanback_leanback",
        "androidx.fragment_fragment",
        "androidx.lifecycle_lifecycle-livedata",
@@ -112,7 +110,6 @@ android_app {
    overrides: ["PackageInstaller"],

    static_libs: [
        "xz-java",
        "androidx.leanback_leanback",
        "androidx.annotation_annotation",
        "androidx.fragment_fragment",
+0 −11
Original line number Diff line number Diff line
@@ -146,17 +146,6 @@
                android:configChanges="mnc|mnc|touchscreen|navigation|screenLayout|screenSize|smallestScreenSize|orientation|locale|keyboard|keyboardHidden|fontScale|uiMode|layoutDirection|density"
                android:exported="false" />

        <!-- Wearable Components -->
        <service android:name=".wear.WearPackageInstallerService"
                 android:permission="com.google.android.permission.INSTALL_WEARABLE_PACKAGES"
                 android:foregroundServiceType="systemExempted"
                 android:exported="true"/>

        <provider android:name=".wear.WearPackageIconProvider"
                  android:authorities="com.google.android.packageinstaller.wear.provider"
                  android:grantUriPermissions="true"
                  android:exported="false" />

        <receiver android:name="androidx.profileinstaller.ProfileInstallReceiver"
            tools:node="remove" />

+0 −173
Original line number Diff line number Diff line
/*
 * 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.packageinstaller.wear;

import android.content.Context;
import android.content.IntentSender;
import android.content.pm.PackageInstaller;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.text.TextUtils;
import android.util.Log;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * Task that installs an APK. This must not be called on the main thread.
 * This code is based off the Finsky/Wearsky implementation
 */
public class InstallTask {
    private static final String TAG = "InstallTask";

    private static final int DEFAULT_BUFFER_SIZE = 8192;

    private final Context mContext;
    private String mPackageName;
    private ParcelFileDescriptor mParcelFileDescriptor;
    private PackageInstallerImpl.InstallListener mCallback;
    private PackageInstaller.Session mSession;
    private IntentSender mCommitCallback;

    private Exception mException = null;
    private int mErrorCode = 0;
    private String mErrorDesc = null;

    public InstallTask(Context context, String packageName,
            ParcelFileDescriptor parcelFileDescriptor,
            PackageInstallerImpl.InstallListener callback, PackageInstaller.Session session,
            IntentSender commitCallback) {
        mContext = context;
        mPackageName = packageName;
        mParcelFileDescriptor = parcelFileDescriptor;
        mCallback = callback;
        mSession = session;
        mCommitCallback = commitCallback;
    }

    public boolean isError() {
        return mErrorCode != InstallerConstants.STATUS_SUCCESS || !TextUtils.isEmpty(mErrorDesc);
    }

    public void execute() {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            throw new IllegalStateException("This method cannot be called from the UI thread.");
        }

        OutputStream sessionStream = null;
        try {
            sessionStream = mSession.openWrite(mPackageName, 0, -1);

            // 2b: Stream the asset to the installer. Note:
            // Note: writeToOutputStreamFromAsset() always safely closes the input stream
            writeToOutputStreamFromAsset(sessionStream);
            mSession.fsync(sessionStream);
        } catch (Exception e) {
            mException = e;
            mErrorCode = InstallerConstants.ERROR_INSTALL_COPY_STREAM;
            mErrorDesc = "Could not write to stream";
        } finally {
            if (sessionStream != null) {
                // 2c: close output stream
                try {
                    sessionStream.close();
                } catch (Exception e) {
                    // Ignore otherwise
                    if (mException == null) {
                        mException = e;
                        mErrorCode = InstallerConstants.ERROR_INSTALL_CLOSE_STREAM;
                        mErrorDesc = "Could not close session stream";
                    }
                }
            }
        }

        if (mErrorCode != InstallerConstants.STATUS_SUCCESS) {
            // An error occurred, we're done
            Log.e(TAG, "Exception while installing " + mPackageName + ": " + mErrorCode + ", "
                    + mErrorDesc + ", " + mException);
            mSession.close();
            mCallback.installFailed(mErrorCode, "[" + mPackageName + "]" + mErrorDesc);
        } else {
            // 3. Commit the session (this actually installs it.)  Session map
            // will be cleaned up in the callback.
            mCallback.installBeginning();
            mSession.commit(mCommitCallback);
            mSession.close();
        }
    }

    /**
     * {@code PackageInstaller} works with streams. Get the {@code FileDescriptor}
     * corresponding to the {@code Asset} and then write the contents into an
     * {@code OutputStream} that is passed in.
     * <br>
     * The {@code FileDescriptor} is closed but the {@code OutputStream} is not closed.
     */
    private boolean writeToOutputStreamFromAsset(OutputStream outputStream) {
        if (outputStream == null) {
            mErrorCode = InstallerConstants.ERROR_INSTALL_COPY_STREAM_EXCEPTION;
            mErrorDesc = "Got a null OutputStream.";
            return false;
        }

        if (mParcelFileDescriptor == null || mParcelFileDescriptor.getFileDescriptor() == null)  {
            mErrorCode = InstallerConstants.ERROR_COULD_NOT_GET_FD;
            mErrorDesc = "Could not get FD";
            return false;
        }

        InputStream inputStream = null;
        try {
            byte[] inputBuf = new byte[DEFAULT_BUFFER_SIZE];
            int bytesRead;
            inputStream = new ParcelFileDescriptor.AutoCloseInputStream(mParcelFileDescriptor);

            while ((bytesRead = inputStream.read(inputBuf)) > -1) {
                if (bytesRead > 0) {
                    outputStream.write(inputBuf, 0, bytesRead);
                }
            }

            outputStream.flush();
        } catch (IOException e) {
            mErrorCode = InstallerConstants.ERROR_INSTALL_APK_COPY_FAILURE;
            mErrorDesc = "Reading from Asset FD or writing to temp file failed: " + e;
            return false;
        } finally {
            safeClose(inputStream);
        }

        return true;
    }

    /**
     * Quietly close a closeable resource (e.g. a stream or file). The input may already
     * be closed and it may even be null.
     */
    public static void safeClose(Closeable resource) {
        if (resource != null) {
            try {
                resource.close();
            } catch (IOException ioe) {
                // Catch and discard the error
            }
        }
    }
}
 No newline at end of file
+0 −59
Original line number Diff line number Diff line
/*
 * 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.packageinstaller.wear;

/**
 * Constants for Installation / Uninstallation requests.
 * Using the same values as Finsky/Wearsky code for consistency in user analytics of failures
 */
public class InstallerConstants {
    /** Request succeeded */
    public static final int STATUS_SUCCESS = 0;

    /**
     * The new PackageInstaller also returns a small set of less granular error codes, which
     * we'll remap to the range -500 and below to keep away from existing installer codes
     * (which run from -1 to -110).
     */
    public final static int ERROR_PACKAGEINSTALLER_BASE = -500;

    public static final int ERROR_COULD_NOT_GET_FD = -603;
    /** This node is not targeted by this request. */

    /** The install did not complete because could not create PackageInstaller session */
    public final static int ERROR_INSTALL_CREATE_SESSION = -612;
    /** The install did not complete because could not open PackageInstaller session  */
    public final static int ERROR_INSTALL_OPEN_SESSION = -613;
    /** The install did not complete because could not open PackageInstaller output stream */
    public final static int ERROR_INSTALL_OPEN_STREAM = -614;
    /** The install did not complete because of an exception while streaming bytes */
    public final static int ERROR_INSTALL_COPY_STREAM_EXCEPTION = -615;
    /** The install did not complete because of an unexpected exception from PackageInstaller */
    public final static int ERROR_INSTALL_SESSION_EXCEPTION = -616;
    /** The install did not complete because of an unexpected userActionRequired callback */
    public final static int ERROR_INSTALL_USER_ACTION_REQUIRED = -617;
    /** The install did not complete because of an unexpected broadcast (missing fields) */
    public final static int ERROR_INSTALL_MALFORMED_BROADCAST = -618;
    /** The install did not complete because of an error while copying from downloaded file */
    public final static int ERROR_INSTALL_APK_COPY_FAILURE = -619;
    /** The install did not complete because of an error while copying to the PackageInstaller
     * output stream */
    public final static int ERROR_INSTALL_COPY_STREAM = -620;
    /** The install did not complete because of an error while closing the PackageInstaller
     * output stream */
    public final static int ERROR_INSTALL_CLOSE_STREAM = -621;
}
 No newline at end of file
+0 −36
Original line number Diff line number Diff line
/*
 * 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.packageinstaller.wear;

import android.content.Context;

/**
 * Factory that creates a Package Installer.
 */
public class PackageInstallerFactory {
    private static PackageInstallerImpl sPackageInstaller;

    /**
     * Return the PackageInstaller shared object. {@code init} should have already been called.
     */
    public synchronized static PackageInstallerImpl getPackageInstaller(Context context) {
        if (sPackageInstaller == null) {
            sPackageInstaller = new PackageInstallerImpl(context);
        }
        return sPackageInstaller;
    }
}
 No newline at end of file
Loading