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

Commit 2277a971 authored by Sumedh Sen's avatar Sumedh Sen
Browse files

Process the incoming intent to this app

This change will simply accept the incoming intent, extract some data from it like the action and whether its a session based install (i.e using the PackageManager APIs). Permission checks and visibility checks would be
added in subsequent changes.

Bug: 182205982
Test: builds successfully
Test: No CTS Tests. Flag to use new app is turned off by default

Change-Id: Ib60593dd0ddc283915c5877a19ec290dbe697839
parent 6f578efd
Loading
Loading
Loading
Loading
+81 −0
Original line number Diff line number Diff line
@@ -17,13 +17,94 @@
package com.android.packageinstaller.v2.model;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageManager;
import android.os.Process;
import android.util.Log;
import com.android.packageinstaller.v2.model.installstagedata.InstallStage;
import com.android.packageinstaller.v2.model.installstagedata.InstallStaging;

public class InstallRepository {

    private static final String TAG = InstallRepository.class.getSimpleName();
    private final Context mContext;
    private final PackageManager mPackageManager;
    private final PackageInstaller mPackageInstaller;
    private final boolean mLocalLOGV = false;
    private Intent mIntent;
    private boolean mIsSessionInstall;
    private boolean mIsTrustedSource;
    /**
     * Session ID for a session created when caller uses PackageInstaller APIs
     */
    private int mSessionId;
    private int mCallingUid;
    private String mCallingPackage;

    public InstallRepository(Context context) {
        mContext = context;
        mPackageManager = context.getPackageManager();
        mPackageInstaller = mPackageManager.getPackageInstaller();
    }

    /**
     * Extracts information from the incoming install intent, checks caller's permission to install
     * packages, verifies that the caller is the install session owner (in case of a session based
     * install) and checks if the current user has restrictions set that prevent app installation,
     * @param intent the incoming {@link Intent} object for installing a package
     * @param callerInfo {@link CallerInfo} that holds the callingUid and callingPackageName
     * @return
     * <p>{@link InstallStaging} after successfully performing the checks</p>
     */
    public InstallStage performPreInstallChecks(Intent intent, CallerInfo callerInfo) {
        mIntent = intent;

        String callingAttributionTag = null;

        mIsSessionInstall =
            PackageInstaller.ACTION_CONFIRM_PRE_APPROVAL.equals(intent.getAction())
                || PackageInstaller.ACTION_CONFIRM_INSTALL.equals(intent.getAction());

        mSessionId = mIsSessionInstall
            ? intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, SessionInfo.INVALID_ID)
            : SessionInfo.INVALID_ID;

        mCallingPackage = callerInfo.getPackageName();

        if (mCallingPackage == null && mSessionId != SessionInfo.INVALID_ID) {
            PackageInstaller.SessionInfo sessionInfo = mPackageInstaller.getSessionInfo(mSessionId);
            mCallingPackage = (sessionInfo != null) ? sessionInfo.getInstallerPackageName() : null;
            callingAttributionTag =
                (sessionInfo != null) ? sessionInfo.getInstallerAttributionTag() : null;
        }

        // Uid of the source package, coming from ActivityManager
        mCallingUid = callerInfo.getUid();
        if (mCallingUid == Process.INVALID_UID) {
            Log.e(TAG, "Could not determine the launching uid.");
        }

        return new InstallStaging();
    }

    public static class CallerInfo {

        private final String mPackageName;
        private final int mUid;

        public CallerInfo(String packageName, int uid) {
            mPackageName = packageName;
            mUid = uid;
        }

        public String getPackageName() {
            return mPackageName;
        }

        public int getUid() {
            return mUid;
        }
    }
}
+27 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.v2.model.installstagedata;

public class InstallStaging extends InstallStage {

    private final int mStage = InstallStage.STAGE_STAGING;

    @Override
    public int getStageCode() {
        return mStage;
    }
}
+19 −0
Original line number Diff line number Diff line
@@ -16,12 +16,17 @@

package com.android.packageinstaller.v2.ui;

import static android.os.Process.INVALID_UID;

import android.content.Intent;
import android.os.Bundle;
import android.view.Window;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.ViewModelProvider;
import com.android.packageinstaller.v2.model.InstallRepository;
import com.android.packageinstaller.v2.model.InstallRepository.CallerInfo;
import com.android.packageinstaller.v2.model.installstagedata.InstallStage;
import com.android.packageinstaller.v2.viewmodel.InstallViewModel;
import com.android.packageinstaller.v2.viewmodel.InstallViewModelFactory;

@@ -45,5 +50,19 @@ public class InstallLaunch extends FragmentActivity {
        mInstallViewModel = new ViewModelProvider(this,
                new InstallViewModelFactory(this.getApplication(), mInstallRepository)).get(
                InstallViewModel.class);

        Intent intent = getIntent();
        CallerInfo info = new CallerInfo(
                intent.getStringExtra(EXTRA_CALLING_PKG_NAME),
                intent.getIntExtra(EXTRA_CALLING_PKG_UID, INVALID_UID));
        mInstallViewModel.preprocessIntent(intent, info);

        mInstallViewModel.getCurrentInstallStage().observe(this, this::onInstallStageChange);
    }

    /**
     * Main controller of the UI. This method shows relevant dialogs based on the install stage
     */
    private void onInstallStageChange(InstallStage installStage) {
    }
}
+17 −1
Original line number Diff line number Diff line
@@ -17,18 +17,34 @@
package com.android.packageinstaller.v2.viewmodel;

import android.app.Application;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.MutableLiveData;
import com.android.packageinstaller.v2.model.InstallRepository;
import com.android.packageinstaller.v2.model.InstallRepository.CallerInfo;
import com.android.packageinstaller.v2.model.installstagedata.InstallStage;
import com.android.packageinstaller.v2.model.installstagedata.InstallStaging;


public class InstallViewModel extends AndroidViewModel {

    private static final String TAG = InstallViewModel.class.getSimpleName();
    private final InstallRepository mRepository;
    private final MutableLiveData<InstallStage> mCurrentInstallStage = new MutableLiveData<>(
            new InstallStaging());

    public InstallViewModel(@NonNull Application application, InstallRepository repository) {
        super(application);
        mRepository = repository;
    }

    public MutableLiveData<InstallStage> getCurrentInstallStage() {
        return mCurrentInstallStage;
    }

    public void preprocessIntent(Intent intent, CallerInfo callerInfo) {
        InstallStage stage = mRepository.performPreInstallChecks(intent, callerInfo);
        mCurrentInstallStage.setValue(stage);
    }
}