1 /*
2  * Copyright (C) 2018 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 
17 package com.android.permissioncontroller.permission.ui.legacy;
18 
19 import static android.content.Intent.ACTION_MANAGE_APP_PERMISSION;
20 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
21 
22 import static com.android.permissioncontroller.Constants.EXTRA_SESSION_ID;
23 import static com.android.permissioncontroller.Constants.INVALID_SESSION_ID;
24 
25 import android.content.Intent;
26 import android.content.pm.PackageManager;
27 import android.content.pm.PermissionGroupInfo;
28 import android.content.pm.PermissionInfo;
29 import android.os.Bundle;
30 import android.os.UserHandle;
31 import android.util.Log;
32 import android.view.MenuItem;
33 
34 import androidx.fragment.app.Fragment;
35 import androidx.fragment.app.FragmentActivity;
36 
37 import com.android.permissioncontroller.DeviceUtils;
38 import com.android.permissioncontroller.R;
39 import com.android.permissioncontroller.permission.ui.LocationProviderInterceptDialog;
40 import com.android.permissioncontroller.permission.ui.ManagePermissionsActivity;
41 import com.android.permissioncontroller.permission.ui.auto.AutoAppPermissionFragment;
42 import com.android.permissioncontroller.permission.ui.television.AppPermissionFragment;
43 import com.android.permissioncontroller.permission.utils.LocationUtils;
44 import com.android.permissioncontroller.permission.utils.PermissionMapping;
45 import com.android.permissioncontroller.permission.utils.Utils;
46 
47 import java.util.List;
48 import java.util.Random;
49 
50 /**
51  * Manage a single permission of a single app.
52  *
53  * @deprecated This class is deprecated for handheld UI, and will throw an error if used for
54  * handheld (read: non auto, TV, or wear) UIs. Instead, users should create an intent with the
55  * ACTION_MANAGE_APP_PERMISSION action, which will intent into the ManagePermissionsActivity.
56  *
57  * @see ManagePermissionsActivity
58  */
59 @Deprecated
60 public final class AppPermissionActivity extends FragmentActivity {
61     private static final String LOG_TAG = AppPermissionActivity.class.getSimpleName();
62 
63     public static final String EXTRA_CALLER_NAME =
64             "com.android.permissioncontroller.extra.CALLER_NAME";
65 
66     // The permission group which was interacted with
67     public static final String EXTRA_RESULT_PERMISSION_INTERACTED = "com.android"
68             + ".permissioncontroller.extra.RESULT_PERMISSION_INTERACTED";
69     /**
70      * The result of the permission in terms of {@link GrantPermissionsViewHandler.Result}
71      */
72     public static final String EXTRA_RESULT_PERMISSION_RESULT = "com.android"
73             + ".permissioncontroller.extra.PERMISSION_RESULT";
74 
75     @Override
onCreate(Bundle savedInstanceState)76     public void onCreate(Bundle savedInstanceState) {
77         if (!DeviceUtils.isAuto(this) && !DeviceUtils.isWear(this)
78                 && !DeviceUtils.isTelevision(this)) {
79             throw new IllegalStateException("Do not use AppPermissionActivity for handheld ui. "
80                     + "Create intent with ACTION_MANAGE_APP_PERMISSION instead.");
81         }
82         if (DeviceUtils.isAuto(this)) {
83             // Automotive relies on a different theme. Apply before calling super so that
84             // fragments are restored properly on configuration changes.
85             setTheme(R.style.CarSettings);
86         }
87         super.onCreate(savedInstanceState);
88 
89         getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
90 
91         String packageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME);
92         if (packageName == null) {
93             Log.e(LOG_TAG, "Missing mandatory argument EXTRA_PACKAGE_NAME");
94             finish();
95             return;
96         }
97 
98         String permissionName = getIntent().getStringExtra(Intent.EXTRA_PERMISSION_NAME);
99         String groupName = getIntent().getStringExtra(Intent.EXTRA_PERMISSION_GROUP_NAME);
100         if (permissionName == null && groupName == null) {
101             Log.e(LOG_TAG, "Missing argument EXTRA_PERMISSION_NAME or "
102                     + "EXTRA_PERMISSION_GROUP_NAME, at least one must be present.");
103             finish();
104             return;
105         }
106         if (groupName == null) {
107             groupName = PermissionMapping.getGroupOfPlatformPermission(permissionName);
108             PermissionInfo permission;
109             try {
110                 permission = getPackageManager().getPermissionInfo(permissionName, 0);
111                 if (!permission.packageName.equals(Utils.OS_PKG)) {
112                     List<PermissionGroupInfo> groupInfos =
113                             getPackageManager().getAllPermissionGroups(0);
114                     for (PermissionGroupInfo groupInfo : groupInfos) {
115                         if (groupInfo.name.equals(permission.group)) {
116                             groupName = permission.group;
117                         }
118                     }
119 
120                 }
121             } catch (PackageManager.NameNotFoundException e) {
122                 groupName = null;
123             }
124         }
125 
126         UserHandle userHandle = getIntent().getParcelableExtra(Intent.EXTRA_USER);
127         if (userHandle == null) {
128             Log.e(LOG_TAG, "Missing mandatory argument EXTRA_USER");
129             finish();
130             return;
131         }
132 
133         if (LocationUtils.isLocationGroupAndProvider(this, groupName,
134                 packageName)) {
135             Intent intent = new Intent(this, LocationProviderInterceptDialog.class);
136             intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
137             startActivityAsUser(intent, userHandle);
138             finish();
139             return;
140         }
141 
142         if (LocationUtils.isLocationGroupAndControllerExtraPackage(
143                 this, groupName, packageName)) {
144             // Redirect to location controller extra package settings.
145             LocationUtils.startLocationControllerExtraPackageSettings(this, userHandle);
146             finish();
147             return;
148         }
149 
150         if (DeviceUtils.isAuto(this)) {
151             Fragment androidXFragment;
152 
153             long sessionId = getIntent().getLongExtra(EXTRA_SESSION_ID, INVALID_SESSION_ID);
154             while (sessionId == INVALID_SESSION_ID) {
155                 sessionId = new Random().nextLong();
156             }
157 
158             androidXFragment = AutoAppPermissionFragment.newInstance(packageName, permissionName,
159                     groupName, userHandle, sessionId);
160 
161             getSupportFragmentManager().beginTransaction().replace(android.R.id.content,
162                     androidXFragment).commit();
163         } else if (DeviceUtils.isTelevision(this)) {
164             Fragment androidXFragment = new AppPermissionFragment();
165             androidXFragment.setArguments(
166                     AppPermissionFragment.createArgs(
167                             packageName, permissionName, groupName, userHandle, null, 0, null));
168             getSupportFragmentManager().beginTransaction()
169                     .replace(android.R.id.content, androidXFragment)
170                     .commit();
171         } else {
172             startActivity(new Intent(getIntent()).setAction(ACTION_MANAGE_APP_PERMISSION));
173             finish();
174         }
175     }
176 
177     @Override
onOptionsItemSelected(MenuItem item)178     public boolean onOptionsItemSelected(MenuItem item) {
179         // in automotive mode, there's no system wide back button, so need to add that
180         if (DeviceUtils.isAuto(this)) {
181             switch (item.getItemId()) {
182                 case android.R.id.home:
183                     onBackPressed();
184                     return true;
185                 default:
186                     return super.onOptionsItemSelected(item);
187             }
188         }
189         return super.onOptionsItemSelected(item);
190     }
191 }
192