• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 The Android Open Source Project
3  * Copyright (C) 2024 Mopria Alliance, Inc.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package com.android.bips.ui
19 
20 import android.graphics.Bitmap
21 import android.graphics.BitmapFactory
22 import android.net.SSLCertificateSocketFactory
23 import android.net.TrafficStats
24 import android.net.Uri
25 import android.util.Log
26 import androidx.lifecycle.LiveData
27 import androidx.lifecycle.MutableLiveData
28 import androidx.lifecycle.ViewModel
29 import androidx.lifecycle.viewModelScope
30 import com.android.bips.BuiltInPrintService
31 import com.android.bips.jni.JobCallbackParams
32 import com.android.bips.jni.LocalPrinterCapabilities
33 import com.android.bips.jni.PrinterStatusMonitor
34 import kotlinx.coroutines.Dispatchers
35 import kotlinx.coroutines.launch
36 import java.io.IOException
37 import java.net.HttpURLConnection
38 import java.net.URL
39 import javax.net.ssl.HostnameVerifier
40 import javax.net.ssl.HttpsURLConnection
41 
42 /**
43  * Printer Information ViewModel
44  */
45 class PrinterInformationViewModel : ViewModel() {
46     companion object {
47         private const val TAG = "PrinterInformationViewModel"
48         private const val DEBUG = false
49     }
50     private val HTTPS = "https"
51     private val HTTP = "http"
52 
53     /** Printer capabilities live data */
54     private val printerCapsLiveData = MutableLiveData<LocalPrinterCapabilities>()
55 
56     /** Printer status live data */
57     private val printerStatusLiveData = MutableLiveData<JobCallbackParams>()
58     private val printerUnavailableLiveData = MutableLiveData<Boolean>()
59     private val printerBitmapLiveData = MutableLiveData<Bitmap>()
60 
61     private lateinit var printerStatusMonitor: PrinterStatusMonitor
62 
63     fun getPrinterCapsLiveData(): LiveData<LocalPrinterCapabilities> {
64         return printerCapsLiveData
65     }
66 
67     fun setPrinterCapsLiveData(localPrinterCapabilities: LocalPrinterCapabilities) {
68         printerCapsLiveData.value = localPrinterCapabilities
69     }
70 
71     fun getPrinterStatusLiveData(): LiveData<JobCallbackParams> {
72         return printerStatusLiveData
73     }
74 
75     fun getPrinterUnavailableLiveData(): LiveData<Boolean> {
76         return printerUnavailableLiveData
77     }
78 
79     fun setPrinterUnavailableLiveData(status: Boolean) {
80         printerUnavailableLiveData.value = status
81     }
82 
83     fun getPrinterBitmapLiveData(): LiveData<Bitmap> {
84         return printerBitmapLiveData
85     }
86 
87     fun getBitmap(iconUri: String) {
88         viewModelScope.launch(Dispatchers.IO) {
89             TrafficStats.setThreadStatsTag(0xF00D)
90             var con: HttpURLConnection? = null
91             try {
92                 if (DEBUG) Log.d(TAG, "Fetching icon from $iconUri")
93                 val url = URL(iconUri)
94                 val protocol = url.protocol
95                 if (protocol.equals(HTTPS, ignoreCase = true)) {
96                     con = url.openConnection() as HttpsURLConnection
97                     (con as HttpsURLConnection?)?.sslSocketFactory =
98                         SSLCertificateSocketFactory.getInsecure(0, null)
99                     (con as HttpsURLConnection?)?.hostnameVerifier =
100                         HostnameVerifier { s, sslSession -> true }
101                 } else if (protocol.equals(HTTP, ignoreCase = true)) {
102                     con = url.openConnection() as HttpURLConnection
103                 } else {
104                     printerBitmapLiveData.postValue(null)
105                 }
106                 con?.doInput = true
107                 con?.connect()
108                 if (DEBUG) Log.d(TAG, "Connected with " + con?.responseCode?.toString())
109                 if (con?.responseCode == HttpURLConnection.HTTP_OK) {
110                     con.inputStream.use { `in` ->
111                         printerBitmapLiveData.postValue(BitmapFactory.decodeStream(`in`))
112                     }
113                 }
114             } catch (e: IllegalStateException) {
115                 if (DEBUG) Log.e(TAG, "Failed to download printer icon $e")
116             } catch (e: IOException) {
117                 if (DEBUG) Log.e(TAG, "Failed to download printer icon $e")
118             } finally {
119                 con?.disconnect()
120                 TrafficStats.clearThreadStatsTag()
121             }
122         }
123     }
124 
125     fun getPrinterStatus(uri: Uri, printService: BuiltInPrintService) {
126         viewModelScope.launch(Dispatchers.IO) {
127             printerStatusMonitor = PrinterStatusMonitor(uri, printService, ::onPrinterStatus)
128         }
129     }
130 
131     fun stopPrinterStatusMonitor(printService: BuiltInPrintService) {
132         if (::printerStatusMonitor.isInitialized) {
133             printerStatusMonitor.stopMonitor(printService)
134         }
135     }
136 
137     private fun onPrinterStatus(status: JobCallbackParams?) {
138         printerStatusLiveData.postValue(status)
139     }
140 }