• 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.PackageManager;
21 import android.net.Uri;
22 import android.os.Binder;
23 import android.os.Bundle;
24 import android.util.Log;
25 
26 import com.android.wallpaper.R;
27 import com.android.wallpaper.model.ImageWallpaperInfo;
28 import com.android.wallpaper.model.WallpaperInfo;
29 import com.android.wallpaper.module.InjectorProvider;
30 import com.android.wallpaper.module.UserEventLogger;
31 
32 import androidx.annotation.NonNull;
33 import androidx.fragment.app.Fragment;
34 import androidx.fragment.app.FragmentManager;
35 
36 /**
37  * Activity that displays a preview of a specific wallpaper and provides the ability to set the
38  * wallpaper as the user's current wallpaper. It's "standalone" meaning it doesn't reside in the
39  * app navigation hierarchy and can be launched directly via an explicit intent.
40  */
41 public class StandalonePreviewActivity extends BasePreviewActivity {
42     private static final String TAG = "StandalonePreview";
43     private static final int READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE = 1;
44 
45     private UserEventLogger mUserEventLogger;
46 
47     @Override
onCreate(Bundle savedInstanceState)48     protected void onCreate(Bundle savedInstanceState) {
49         super.onCreate(savedInstanceState);
50         setContentView(R.layout.activity_preview);
51 
52         mUserEventLogger = InjectorProvider.getInjector().getUserEventLogger(getApplicationContext());
53         mUserEventLogger.logStandalonePreviewLaunched();
54 
55         Intent cropAndSetWallpaperIntent = getIntent();
56         Uri imageUri = cropAndSetWallpaperIntent.getData();
57 
58         if (imageUri == null) {
59             Log.e(TAG, "No URI passed in intent; exiting StandalonePreviewActivity");
60             finish();
61             return;
62         }
63 
64         // Check if READ_EXTERNAL_STORAGE permission is needed because the app invoking this activity
65         // passed a file:// URI or a content:// URI without a flag to grant read permission.
66         boolean isReadPermissionGrantedForImageUri = isReadPermissionGrantedForImageUri(imageUri);
67         mUserEventLogger.logStandalonePreviewImageUriHasReadPermission(
68                 isReadPermissionGrantedForImageUri);
69 
70         // Request storage permission if necessary (i.e., on Android M and later if storage permission
71         // has not already been granted) and delay loading the PreviewFragment until the permission is
72         // granted.
73         if (!isReadPermissionGrantedForImageUri && !isReadExternalStoragePermissionGrantedForApp()) {
74             requestPermissions(
75                     new String[]{permission.READ_EXTERNAL_STORAGE},
76                     READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE);
77         }
78     }
79 
80     @Override
onAttachedToWindow()81     public void onAttachedToWindow() {
82         super.onAttachedToWindow();
83 
84         FragmentManager fragmentManager = getSupportFragmentManager();
85         Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_container);
86 
87         if (fragment == null) {
88             loadPreviewFragment();
89         }
90     }
91 
92     @Override
onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)93     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
94                                            @NonNull int[] grantResults) {
95         // Load the preview fragment if the storage permission was granted.
96         if (requestCode == READ_EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE) {
97             boolean isGranted = permissions.length > 0
98                     && permissions[0].equals(permission.READ_EXTERNAL_STORAGE)
99                     && grantResults.length > 0
100                     && grantResults[0] == PackageManager.PERMISSION_GRANTED;
101 
102             mUserEventLogger.logStandalonePreviewStorageDialogApproved(isGranted);
103 
104             // Close the activity because we can't open the image without storage permission.
105             if (!isGranted) {
106                 finish();
107             }
108 
109             loadPreviewFragment();
110         }
111     }
112 
113     /**
114      * Creates a new instance of {@link PreviewFragment} and loads the fragment into this activity's
115      * fragment container so that it's shown to the user.
116      */
loadPreviewFragment()117     private void loadPreviewFragment() {
118         Intent intent = getIntent();
119 
120         boolean testingModeEnabled = intent.getBooleanExtra(EXTRA_TESTING_MODE_ENABLED, false);
121         WallpaperInfo wallpaper = new ImageWallpaperInfo(intent.getData());
122         Fragment fragment = InjectorProvider.getInjector().getPreviewFragment(
123                 /* context */ this,
124                 wallpaper,
125                 PreviewFragment.MODE_CROP_AND_SET_WALLPAPER,
126                 testingModeEnabled);
127         getSupportFragmentManager().beginTransaction()
128                 .add(R.id.fragment_container, fragment)
129                 .commit();
130     }
131 
132     /**
133      * Returns whether the user has granted READ_EXTERNAL_STORAGE permission to the app.
134      */
isReadExternalStoragePermissionGrantedForApp()135     private boolean isReadExternalStoragePermissionGrantedForApp() {
136         return getPackageManager().checkPermission(permission.READ_EXTERNAL_STORAGE,
137                 getPackageName()) == PackageManager.PERMISSION_GRANTED;
138     }
139 
140     /**
141      * Returns whether the provided image Uri is readable without requiring the app to have the user
142      * grant READ_EXTERNAL_STORAGE permission.
143      */
isReadPermissionGrantedForImageUri(Uri imageUri)144     private boolean isReadPermissionGrantedForImageUri(Uri imageUri) {
145         return checkUriPermission(
146                 imageUri,
147                 Binder.getCallingPid(),
148                 Binder.getCallingUid(),
149                 Intent.FLAG_GRANT_READ_URI_PERMISSION) == PackageManager.PERMISSION_GRANTED;
150     }
151 }
152