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

Commit bf3079a2 authored by Babak Bostan's avatar Babak Bostan Committed by Android (Google) Code Review
Browse files

Merge "Add side loaded listener and controller" into rvc-dev

parents cb16fcd4 16648aff
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -111,5 +111,6 @@
        <item>com.android.systemui.car.voicerecognition.ConnectedDeviceVoiceRecognitionNotifier</item>
        <item>com.android.systemui.car.window.SystemUIOverlayWindowManager</item>
        <item>com.android.systemui.car.volume.VolumeUI</item>
        <item>com.android.systemui.car.sideloaded.SideLoadedAppController</item>
    </string-array>
</resources>
+7 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import com.android.systemui.biometrics.AuthController;
import com.android.systemui.bubbles.dagger.BubbleModule;
import com.android.systemui.car.navigationbar.CarNavigationBar;
import com.android.systemui.car.notification.CarNotificationModule;
import com.android.systemui.car.sideloaded.SideLoadedAppController;
import com.android.systemui.car.statusbar.CarStatusBar;
import com.android.systemui.car.statusbar.CarStatusBarModule;
import com.android.systemui.car.voicerecognition.ConnectedDeviceVoiceRecognitionNotifier;
@@ -192,4 +193,10 @@ public abstract class CarSystemUIBinder {
    @IntoMap
    @ClassKey(SystemUIOverlayWindowManager.class)
    public abstract SystemUI bindSystemUIPrimaryWindowManager(SystemUIOverlayWindowManager sysui);

    /** Inject into SideLoadedAppController. */
    @Binds
    @IntoMap
    @ClassKey(SideLoadedAppController.class)
    public abstract SystemUI bindSideLoadedAppController(SideLoadedAppController sysui);
}
+73 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.systemui.car.sideloaded;

import android.app.IActivityTaskManager;
import android.content.Context;
import android.os.RemoteException;
import android.util.Log;

import com.android.systemui.SystemUI;

import javax.inject.Inject;
import javax.inject.Singleton;

/**
 * Controller responsible for detecting unsafe apps.
 */
@Singleton
public class SideLoadedAppController extends SystemUI {
    private static final String TAG = SideLoadedAppController.class.getSimpleName();

    private IActivityTaskManager mActivityTaskManager;
    private SideLoadedAppListener mSideLoadedAppListener;
    private SideLoadedAppDetector mSideLoadedAppDetector;
    private SideLoadedAppStateController mSideLoadedAppStateController;

    @Inject
    public SideLoadedAppController(Context context,
            IActivityTaskManager activityTaskManager,
            SideLoadedAppDetector sideLoadedAppDetector,
            SideLoadedAppListener sideLoadedAppListener,
            SideLoadedAppStateController sideLoadedAppStateController) {
        super(context);

        mSideLoadedAppDetector = sideLoadedAppDetector;
        mActivityTaskManager = activityTaskManager;
        mSideLoadedAppListener = sideLoadedAppListener;
        mSideLoadedAppStateController = sideLoadedAppStateController;
    }

    @Override
    public void start() {
    }

    @Override
    protected void onBootCompleted() {
        Log.i(TAG, "OnBootCompleted");

        try {
            mActivityTaskManager.registerTaskStackListener(mSideLoadedAppListener);
        } catch (RemoteException e) {
            Log.e(TAG, "Could not register car side loaded app listener.", e);
        }

        if (mSideLoadedAppDetector.hasUnsafeInstalledApps()) {
            mSideLoadedAppStateController.onUnsafeInstalledAppsDetected();
        }
    }
}
+3 −3
Original line number Diff line number Diff line
@@ -42,15 +42,15 @@ import javax.inject.Singleton;
 * An app is considered safe if is a system app or installed through whitelisted sources.
 */
@Singleton
public class CarSideLoadedAppDetector {
    private static final String TAG = "CarSideLoadedDetector";
public class SideLoadedAppDetector {
    private static final String TAG = SideLoadedAppDetector.class.getSimpleName();

    private final PackageManager mPackageManager;
    private final CarDeviceProvisionedController mCarDeviceProvisionedController;
    private final List<String> mAllowedAppInstallSources;

    @Inject
    public CarSideLoadedAppDetector(@Main Resources resources, PackageManager packageManager,
    public SideLoadedAppDetector(@Main Resources resources, PackageManager packageManager,
            CarDeviceProvisionedController deviceProvisionedController) {
        mAllowedAppInstallSources = Arrays.asList(
                resources.getStringArray(R.array.config_allowedAppInstallSources));
+130 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.systemui.car.sideloaded;

import android.app.ActivityManager;
import android.app.ActivityManager.StackInfo;
import android.app.IActivityTaskManager;
import android.app.TaskStackListener;
import android.content.ComponentName;
import android.hardware.display.DisplayManager;
import android.os.RemoteException;
import android.util.Log;
import android.view.Display;

import java.util.List;

import javax.inject.Inject;

/**
 * A TaskStackListener to detect when an unsafe app is launched/foregrounded.
 */
public class SideLoadedAppListener extends TaskStackListener {
    private static final String TAG = SideLoadedAppListener.class.getSimpleName();

    private IActivityTaskManager mActivityTaskManager;
    private DisplayManager mDisplayManager;
    private SideLoadedAppDetector mSideLoadedAppDetector;
    private SideLoadedAppStateController mSideLoadedAppStateController;

    @Inject
    SideLoadedAppListener(SideLoadedAppDetector sideLoadedAppDetector,
            IActivityTaskManager activityTaskManager,
            DisplayManager displayManager,
            SideLoadedAppStateController sideLoadedAppStateController) {
        mSideLoadedAppDetector = sideLoadedAppDetector;
        mActivityTaskManager = activityTaskManager;
        mDisplayManager = displayManager;
        mSideLoadedAppStateController = sideLoadedAppStateController;
    }

    @Override
    public void onTaskCreated(int taskId, ComponentName componentName) throws RemoteException {
        super.onTaskCreated(taskId, componentName);

        List<StackInfo> stackInfoList = mActivityTaskManager.getAllStackInfos();
        ActivityManager.StackInfo stackInfo = getStackInfo(stackInfoList, taskId);
        if (stackInfo == null) {
            Log.e(TAG, "Stack info was not available for taskId: " + taskId);
            return;
        }

        if (!mSideLoadedAppDetector.isSafe(stackInfo)) {
            Display display = mDisplayManager.getDisplay(stackInfo.displayId);
            mSideLoadedAppStateController.onUnsafeTaskCreatedOnDisplay(display);
        }
    }

    @Override
    public void onTaskStackChanged() throws RemoteException {
        super.onTaskStackChanged();

        Display[] displays = mDisplayManager.getDisplays();
        for (Display display : displays) {
            // Note that the stackInfoList is ordered by recency.
            List<StackInfo> stackInfoList =
                    mActivityTaskManager.getAllStackInfosOnDisplay(display.getDisplayId());

            if (stackInfoList == null) {
                continue;
            }
            StackInfo stackInfo = getTopVisibleStackInfo(stackInfoList);
            if (stackInfo == null) {
                continue;
            }
            if (mSideLoadedAppDetector.isSafe(stackInfo)) {
                mSideLoadedAppStateController.onSafeTaskDisplayedOnDisplay(display);
            } else {
                mSideLoadedAppStateController.onUnsafeTaskDisplayedOnDisplay(display);
            }
        }
    }

    /**
     * Returns stack info for a given taskId.
     */
    private ActivityManager.StackInfo getStackInfo(
            List<ActivityManager.StackInfo> stackInfoList, int taskId) {
        if (stackInfoList == null) {
            return null;
        }
        for (ActivityManager.StackInfo stackInfo : stackInfoList) {
            if (stackInfo.taskIds == null) {
                continue;
            }
            for (int stackTaskId : stackInfo.taskIds) {
                if (taskId == stackTaskId) {
                    return stackInfo;
                }
            }
        }
        return null;
    }

    /**
     * Returns the first visible stackInfo.
     */
    private ActivityManager.StackInfo getTopVisibleStackInfo(
            List<ActivityManager.StackInfo> stackInfoList) {
        for (ActivityManager.StackInfo stackInfo : stackInfoList) {
            if (stackInfo.visible) {
                return stackInfo;
            }
        }
        return null;
    }
}
Loading