• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 package com.android.wallpaper.picker;
17 
18 import android.Manifest.permission;
19 import android.content.Intent;
20 import android.content.pm.ActivityInfo;
21 import android.content.pm.PackageManager;
22 import android.content.res.Resources;
23 import android.net.Uri;
24 import android.os.Binder;
25 import android.os.Bundle;
26 import android.util.Log;
27 
28 import androidx.annotation.NonNull;
29 import androidx.fragment.app.Fragment;
30 import androidx.fragment.app.FragmentManager;
31 
32 import com.android.wallpaper.R;
33 import com.android.wallpaper.config.BaseFlags;
34 import com.android.wallpaper.model.ImageWallpaperInfo;
35 import com.android.wallpaper.model.WallpaperInfo;
36 import com.android.wallpaper.module.InjectorProvider;
37 import com.android.wallpaper.module.UserEventLogger;
38 import com.android.wallpaper.picker.AppbarFragment.AppbarFragmentHost;
39 import com.android.wallpaper.picker.preview.ui.WallpaperPreviewActivity;
40 
41 /**
42  * Activity that displays a preview of a specific wallpaper and provides the ability to set the
43  * wallpaper as the user's current wallpaper. It's "standalone" meaning it doesn't reside in the
44  * app navigation hierarchy and can be launched directly via an explicit intent.
45  */
46 public class StandalonePreviewActivity extends BasePreviewActivity implements AppbarFragmentHost {
47     private static final String TAG = "StandalonePreview";
48     private static final String KEY_UP_ARROW = "up_arrow";
49     private static final int READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE = 1;
50 
51     private UserEventLogger mUserEventLogger;
52 
53     @Override
onCreate(Bundle savedInstanceState)54     protected void onCreate(Bundle savedInstanceState) {
55         super.onCreate(savedInstanceState);
56         setContentView(R.layout.activity_preview);
57 
58         enableFullScreen();
59 
60         mUserEventLogger = InjectorProvider.getInjector().getUserEventLogger(
61                 getApplicationContext());
62         mUserEventLogger.logStandalonePreviewLaunched();
63 
64         Intent cropAndSetWallpaperIntent = getIntent();
65         Uri imageUri = cropAndSetWallpaperIntent.getData();
66 
67         if (imageUri == null) {
68             Log.e(TAG, "No URI passed in intent; exiting StandalonePreviewActivity");
69             finish();
70             return;
71         }
72 
73         // Check if READ_MEDIA_IMAGES permission is needed because the app invoking this activity
74         // passed a file:// URI or a content:// URI without a flag to grant read permission.
75         boolean isReadPermissionGrantedForImageUri = isReadPermissionGrantedForImageUri(imageUri);
76         mUserEventLogger.logStandalonePreviewImageUriHasReadPermission(
77                 isReadPermissionGrantedForImageUri);
78 
79         // Request storage permission if necessary (i.e., on Android M and later if storage
80         // permission has not already been granted) and delay loading the PreviewFragment until the
81         // permission is granted.
82         if (!isReadPermissionGrantedForImageUri
83                 && !isReadExternalStoragePermissionGrantedForApp()) {
84             requestPermissions(
85                     new String[]{permission.READ_MEDIA_IMAGES},
86                     READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE);
87         }
88     }
89 
90     @Override
onAttachedToWindow()91     public void onAttachedToWindow() {
92         super.onAttachedToWindow();
93 
94         FragmentManager fragmentManager = getSupportFragmentManager();
95         Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_container);
96 
97         if (fragment == null) {
98             loadPreviewFragment();
99         }
100     }
101 
102     @SuppressWarnings("MissingSuperCall") // TODO: Fix me
103     @Override
onResume()104     protected void onResume() {
105         super.onResume();
106         Resources res = getResources();
107         boolean isDeviceFoldableOrTablet = res.getBoolean(R.bool.is_large_screen);
108 
109         if (!isDeviceFoldableOrTablet) {
110             setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
111         }
112     }
113 
114     @SuppressWarnings("MissingSuperCall") // TODO: Fix me
115     @Override
onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)116     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
117             @NonNull int[] grantResults) {
118         // Load the preview fragment if the storage permission was granted.
119         if (requestCode == READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE) {
120             boolean isGranted = permissions.length > 0
121                     && permissions[0].equals(permission.READ_MEDIA_IMAGES)
122                     && grantResults.length > 0
123                     && grantResults[0] == PackageManager.PERMISSION_GRANTED;
124 
125             mUserEventLogger.logStandalonePreviewStorageDialogApproved(isGranted);
126 
127             // Close the activity because we can't open the image without storage permission.
128             if (!isGranted) {
129                 finish();
130             }
131 
132             loadPreviewFragment();
133         }
134     }
135 
136     // TODO(b/182972395): It should go back to WallpaperPicker.
137     @Override
onUpArrowPressed()138     public void onUpArrowPressed() {
139         // Enable back functions for multi-pane.
140         onBackPressed();
141     }
142 
143     // TODO(b/182972395): It should go back to WallpaperPicker.
144     @Override
isUpArrowSupported()145     public boolean isUpArrowSupported() {
146         // Show up arrow for multi-pane.
147         return getIntent().getBooleanExtra(KEY_UP_ARROW, false);
148     }
149 
150     /**
151      * Creates a new instance of {@link PreviewFragment} and loads the fragment into this
152      * activity's fragment container so that it's shown to the user.
153      */
loadPreviewFragment()154     private void loadPreviewFragment() {
155         BaseFlags flags = InjectorProvider.getInjector().getFlags();
156         Intent intent = getIntent();
157         WallpaperInfo wallpaper = new ImageWallpaperInfo(intent.getData());
158         if (flags.isMultiCropPreviewUiEnabled() && flags.isMultiCropEnabled()) {
159             startActivity(WallpaperPreviewActivity.Companion.newIntent(
160                     this.getApplicationContext(), wallpaper, /* isNewTask= */ false));
161             finish();
162             return;
163         }
164         Fragment fragment = InjectorProvider.getInjector().getPreviewFragment(
165                 /* context */ this,
166                 wallpaper,
167                 /* viewAsHome= */ true,
168                 /* isAssetIdPresent= */ false,
169                 /* isNewTask= */ false);
170         getSupportFragmentManager().beginTransaction()
171                 .add(R.id.fragment_container, fragment)
172                 .commit();
173     }
174 
175     /**
176      * Returns whether the user has granted READ_MEDIA_IMAGES permission to the app.
177      */
isReadExternalStoragePermissionGrantedForApp()178     private boolean isReadExternalStoragePermissionGrantedForApp() {
179         return getPackageManager().checkPermission(permission.READ_MEDIA_IMAGES,
180                 getPackageName()) == PackageManager.PERMISSION_GRANTED;
181     }
182 
183     /**
184      * Returns whether the provided image Uri is readable without requiring the app to have the user
185      * grant READ_MEDIA_IMAGES permission.
186      */
isReadPermissionGrantedForImageUri(Uri imageUri)187     private boolean isReadPermissionGrantedForImageUri(Uri imageUri) {
188         return checkUriPermission(
189                 imageUri,
190                 Binder.getCallingPid(),
191                 Binder.getCallingUid(),
192                 Intent.FLAG_GRANT_READ_URI_PERMISSION) == PackageManager.PERMISSION_GRANTED;
193     }
194 }
195