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

Commit bc013406 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes from topic "ongoing-usage-dialog-migration"

* changes:
  Launch external ongoing usage dialog instead of internal one.
  Add an API to launch the ongoing usage dialog.
parents 33b6db9d f8b6292d
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -1430,8 +1430,9 @@ package android.content {
    field public static final String ACTION_RESOLVE_INSTANT_APP_PACKAGE = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE";
    field @RequiresPermission(android.Manifest.permission.REVIEW_ACCESSIBILITY_SERVICES) public static final String ACTION_REVIEW_ACCESSIBILITY_SERVICES = "android.intent.action.REVIEW_ACCESSIBILITY_SERVICES";
    field @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public static final String ACTION_REVIEW_APP_PERMISSION_USAGE = "android.intent.action.REVIEW_APP_PERMISSION_USAGE";
    field @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public static final String ACTION_REVIEW_ONGOING_PERMISSION_USAGE = "android.intent.action.REVIEW_ONGOING_PERMISSION_USAGE";
    field public static final String ACTION_REVIEW_PERMISSIONS = "android.intent.action.REVIEW_PERMISSIONS";
    field public static final String ACTION_REVIEW_PERMISSION_USAGE = "android.intent.action.REVIEW_PERMISSION_USAGE";
    field @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public static final String ACTION_REVIEW_PERMISSION_USAGE = "android.intent.action.REVIEW_PERMISSION_USAGE";
    field public static final String ACTION_ROLLBACK_COMMITTED = "android.intent.action.ROLLBACK_COMMITTED";
    field public static final String ACTION_SHOW_SUSPENDED_APP_DETAILS = "android.intent.action.SHOW_SUSPENDED_APP_DETAILS";
    field @Deprecated public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
+0 −1
Original line number Diff line number Diff line
@@ -3422,7 +3422,6 @@ message HiddenApiUsed {
 * - When user clicks privacy chip
 * - How does the user exit the Privacy Dialog
 * Logged from:
 *   packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
 *   packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
 */
message PrivacyIndicatorsInteracted {
+27 −0
Original line number Diff line number Diff line
@@ -2078,6 +2078,9 @@ public class Intent implements Parcelable, Cloneable {
     * <p>
     * Output: Nothing.
     * </p>
     * <p class="note">
     * This requires {@link android.Manifest.permission#GRANT_RUNTIME_PERMISSIONS} permission.
     * </p>
     *
     * @see #EXTRA_PERMISSION_NAME
     * @see #EXTRA_PERMISSION_GROUP_NAME
@@ -2086,10 +2089,34 @@ public class Intent implements Parcelable, Cloneable {
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_REVIEW_PERMISSION_USAGE =
            "android.intent.action.REVIEW_PERMISSION_USAGE";

    /**
     * Activity action: Launch UI to review ongoing app uses of permissions.
     * <p>
     * Input: {@link #EXTRA_DURATION_MILLIS} specifies the minimum number of milliseconds of recent
     * activity to show (optional).  Must be non-negative.
     * </p>
     * <p>
     * Output: Nothing.
     * </p>
     * <p class="note">
     * This requires {@link android.Manifest.permission#GRANT_RUNTIME_PERMISSIONS} permission.
     * </p>
     *
     * @see #EXTRA_DURATION_MILLIS
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_REVIEW_ONGOING_PERMISSION_USAGE =
            "android.intent.action.REVIEW_ONGOING_PERMISSION_USAGE";

    /**
     * Activity action: Launch UI to review uses of permissions for a single app.
     * <p>
+0 −160
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.privacy

import android.app.AlertDialog
import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.pm.PackageManager
import android.content.res.ColorStateList
import android.os.UserHandle
import android.provider.Settings
import android.util.IconDrawableFactory
import android.util.StatsLog
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.android.systemui.Dependency
import com.android.systemui.R
import com.android.systemui.plugins.ActivityStarter
import java.util.concurrent.TimeUnit

class OngoingPrivacyDialog constructor(
    private val context: Context,
    private val dialogBuilder: PrivacyDialogBuilder
) {

    private val iconSize = context.resources.getDimensionPixelSize(
            R.dimen.ongoing_appops_dialog_icon_size)
    private val iconColor = context.resources.getColor(
            com.android.internal.R.color.text_color_primary, context.theme)
    private val iconMargin = context.resources.getDimensionPixelSize(
            R.dimen.ongoing_appops_dialog_icon_margin)
    private val iconFactory = IconDrawableFactory.newInstance(context, true)
    private var dismissDialog: (() -> Unit)? = null
    private val appsAndTypes = dialogBuilder.appsAndTypes
            .sortedWith(compareBy({ -it.second.size }, // Sort by number of AppOps
            { it.second.min() },
            { it.first }))

    fun createDialog(): Dialog {
        val builder = AlertDialog.Builder(context).apply {
            setPositiveButton(R.string.ongoing_privacy_dialog_ok,
                    object : DialogInterface.OnClickListener {
                override fun onClick(dialog: DialogInterface?, which: Int) {
                    StatsLog.write(StatsLog.PRIVACY_INDICATORS_INTERACTED,
                            StatsLog.PRIVACY_INDICATORS_INTERACTED__TYPE__DIALOG_DISMISS)
                }
            })
            setNeutralButton(R.string.ongoing_privacy_dialog_open_settings,
                    object : DialogInterface.OnClickListener {
                        val intent = Intent(Settings.ACTION_PRIVACY_SETTINGS).putExtra(
                                Intent.EXTRA_DURATION_MILLIS, TimeUnit.MINUTES.toMillis(1))

                        @Suppress("DEPRECATION")
                        override fun onClick(dialog: DialogInterface?, which: Int) {
                            StatsLog.write(StatsLog.PRIVACY_INDICATORS_INTERACTED, StatsLog
                                    .PRIVACY_INDICATORS_INTERACTED__TYPE__DIALOG_PRIVACY_SETTINGS)
                            Dependency.get(ActivityStarter::class.java)
                                    .postStartActivityDismissingKeyguard(intent, 0)
                        }
                    })
        }
        builder.setView(getContentView())
        val dialog = builder.create()
        dismissDialog = dialog::dismiss
        return dialog
    }

    fun getContentView(): View {
        val layoutInflater = LayoutInflater.from(context)
        val contentView = layoutInflater.inflate(R.layout.ongoing_privacy_dialog_content, null)

        val title = contentView.findViewById(R.id.title) as TextView
        val appsList = contentView.findViewById(R.id.items_container) as LinearLayout

        title.setText(dialogBuilder.getDialogTitle())

        val numItems = appsAndTypes.size
        for (i in 0..(numItems - 1)) {
            val item = appsAndTypes[i]
            addAppItem(appsList, item.first, item.second, dialogBuilder.types.size > 1)
        }
        return contentView
    }

    @Suppress("DEPRECATION")
    private fun addAppItem(
        itemList: LinearLayout,
        app: PrivacyApplication,
        types: List<PrivacyType>,
        showIcons: Boolean = true
    ) {
        val layoutInflater = LayoutInflater.from(context)
        val item = layoutInflater.inflate(R.layout.ongoing_privacy_dialog_item, itemList, false)
        val appIcon = item.findViewById(R.id.app_icon) as ImageView
        val appName = item.findViewById(R.id.app_name) as TextView
        val icons = item.findViewById(R.id.icons) as LinearLayout

        val lp = LinearLayout.LayoutParams(iconSize, iconSize).apply {
            gravity = Gravity.CENTER_VERTICAL
            marginStart = iconMargin
        }

        app.icon.let {
            appIcon.setImageDrawable(iconFactory.getShadowedIcon(it))
        }

        appName.text = app.applicationName
        if (showIcons) {
            dialogBuilder.generateIconsForApp(types).forEachIndexed { index, it ->
                it.setBounds(0, 0, iconSize, iconSize)
                val image = ImageView(context).apply {
                    imageTintList = ColorStateList.valueOf(iconColor)
                    setImageDrawable(it)
                }
                image.contentDescription = types[index].getName(context)
                icons.addView(image, lp)
            }
            icons.visibility = View.VISIBLE
        } else {
            icons.visibility = View.GONE
        }
        try {
            // Check if package exists
            context.packageManager.getPackageInfo(app.packageName, 0)
            item.setOnClickListener(object : View.OnClickListener {
                val intent = Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS)
                        .putExtra(Intent.EXTRA_PACKAGE_NAME, app.packageName)
                        .putExtra(Intent.EXTRA_USER, UserHandle.getUserHandleForUid(app.uid))
                override fun onClick(v: View?) {
                    StatsLog.write(StatsLog.PRIVACY_INDICATORS_INTERACTED,
                            StatsLog.PRIVACY_INDICATORS_INTERACTED__TYPE__DIALOG_LINE_ITEM,
                            app.packageName)
                    Dependency.get(ActivityStarter::class.java)
                            .postStartActivityDismissingKeyguard(intent, 0)
                    dismissDialog?.invoke()
                }
            })
        } catch (e: PackageManager.NameNotFoundException) {}

        itemList.addView(item)
    }
}
+2 −8
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import android.animation.AnimatorListenerAdapter;
import android.annotation.ColorInt;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -62,7 +61,6 @@ import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.privacy.OngoingPrivacyChip;
import com.android.systemui.privacy.OngoingPrivacyDialog;
import com.android.systemui.privacy.PrivacyDialogBuilder;
import com.android.systemui.privacy.PrivacyItem;
import com.android.systemui.privacy.PrivacyItemController;
@@ -71,7 +69,6 @@ import com.android.systemui.statusbar.phone.PhoneStatusBarView;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
import com.android.systemui.statusbar.phone.StatusIconContainer;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.Clock;
import com.android.systemui.statusbar.policy.DateView;
import com.android.systemui.statusbar.policy.NextAlarmController;
@@ -561,11 +558,8 @@ public class QuickStatusBarHeader extends RelativeLayout implements
            StatsLog.write(StatsLog.PRIVACY_INDICATORS_INTERACTED,
                    StatsLog.PRIVACY_INDICATORS_INTERACTED__TYPE__CHIP_CLICKED);
            mUiHandler.post(() -> {
                Dialog mDialog = new OngoingPrivacyDialog(mContext, builder).createDialog();
                SystemUIDialog.setShowForAllUsers(mDialog, false);
                SystemUIDialog.registerDismissListener(mDialog);
                SystemUIDialog.setWindowOnTop(mDialog);
                mActivityStarter.postQSRunnableDismissingKeyguard(() -> mDialog.show());
                mActivityStarter.postStartActivityDismissingKeyguard(
                        new Intent(Intent.ACTION_REVIEW_ONGOING_PERMISSION_USAGE), 0);
                mHost.collapsePanels();
            });
        }