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 17 package com.android.server.wm; 18 19 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 20 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 21 22 import android.app.ActivityManager.TaskSnapshot; 23 import android.content.ComponentName; 24 import android.graphics.Bitmap; 25 import android.graphics.Bitmap.Config; 26 import android.graphics.BitmapFactory; 27 import android.graphics.BitmapFactory.Options; 28 import android.graphics.GraphicBuffer; 29 import android.graphics.Rect; 30 import android.util.Slog; 31 32 import com.android.server.wm.nano.WindowManagerProtos.TaskSnapshotProto; 33 34 import java.io.File; 35 import java.io.IOException; 36 import java.nio.file.Files; 37 38 /** 39 * Loads a persisted {@link TaskSnapshot} from disk. 40 * <p> 41 * Do not hold the window manager lock when accessing this class. 42 * <p> 43 * Test class: {@link TaskSnapshotPersisterLoaderTest} 44 */ 45 class TaskSnapshotLoader { 46 47 private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskSnapshotLoader" : TAG_WM; 48 49 private final TaskSnapshotPersister mPersister; 50 TaskSnapshotLoader(TaskSnapshotPersister persister)51 TaskSnapshotLoader(TaskSnapshotPersister persister) { 52 mPersister = persister; 53 } 54 55 /** 56 * Loads a task from the disk. 57 * <p> 58 * Do not hold the window manager lock when calling this method, as we directly read data from 59 * disk here, which might be slow. 60 * 61 * @param taskId The id of the task to load. 62 * @param userId The id of the user the task belonged to. 63 * @param reducedResolution Whether to load a reduced resolution version of the snapshot. 64 * @return The loaded {@link TaskSnapshot} or {@code null} if it couldn't be loaded. 65 */ loadTask(int taskId, int userId, boolean reducedResolution)66 TaskSnapshot loadTask(int taskId, int userId, boolean reducedResolution) { 67 final File protoFile = mPersister.getProtoFile(taskId, userId); 68 final File bitmapFile = reducedResolution 69 ? mPersister.getReducedResolutionBitmapFile(taskId, userId) 70 : mPersister.getBitmapFile(taskId, userId); 71 if (bitmapFile == null || !protoFile.exists() || !bitmapFile.exists()) { 72 return null; 73 } 74 try { 75 final byte[] bytes = Files.readAllBytes(protoFile.toPath()); 76 final TaskSnapshotProto proto = TaskSnapshotProto.parseFrom(bytes); 77 final Options options = new Options(); 78 options.inPreferredConfig = Config.HARDWARE; 79 final Bitmap bitmap = BitmapFactory.decodeFile(bitmapFile.getPath(), options); 80 if (bitmap == null) { 81 Slog.w(TAG, "Failed to load bitmap: " + bitmapFile.getPath()); 82 return null; 83 } 84 final GraphicBuffer buffer = bitmap.createGraphicBufferHandle(); 85 if (buffer == null) { 86 Slog.w(TAG, "Failed to retrieve gralloc buffer for bitmap: " 87 + bitmapFile.getPath()); 88 return null; 89 } 90 final ComponentName topActivityComponent = ComponentName.unflattenFromString( 91 proto.topActivityComponent); 92 // For legacy snapshots, restore the scale based on the reduced resolution state 93 final float legacyScale = reducedResolution ? mPersister.getReducedScale() : 1f; 94 final float scale = Float.compare(proto.scale, 0f) != 0 ? proto.scale : legacyScale; 95 return new TaskSnapshot(topActivityComponent, buffer, bitmap.getColorSpace(), 96 proto.orientation, 97 new Rect(proto.insetLeft, proto.insetTop, proto.insetRight, proto.insetBottom), 98 reducedResolution, scale, proto.isRealSnapshot, proto.windowingMode, 99 proto.systemUiVisibility, proto.isTranslucent); 100 } catch (IOException e) { 101 Slog.w(TAG, "Unable to load task snapshot data for taskId=" + taskId); 102 return null; 103 } 104 } 105 } 106